Home > .NET, ASP.NET, CSS, Themes and Skins > The Problems with Themes, Skins, and Cascading Style Sheets (CSS) in ASP.NET 2.0 – Using Internal (Embedded) Style Sheets with Themes (Work Around #4)

The Problems with Themes, Skins, and Cascading Style Sheets (CSS) in ASP.NET 2.0 – Using Internal (Embedded) Style Sheets with Themes (Work Around #4)

February 5th, 2007

ASP.NET 2.0′s Themes and Skins have a number of design flaws – Themes and Skins depend almost entirely on Cascading Stye Sheet (CSS), but don’t fully support CSS – I’ve listed some “Work Arounds” for a couple design flaws. I don’t recommend any of these “Work Arounds” since they contribute to software entropy before your application is even developed, instead I suggest sticking with CSS and perhaps using some default Skins that define CSS selectors like classes or IDs.

The Problem / Question:
How can I add Internal (embedded) style sheets (the ones that use the Style element) inside the Head tag when using Master Pages and Themes?  How can I override (overload) External style sheets for local pages or specific Web User Controls?

A Solution / Work Around:

One option is to create an ASP Placeholder (asp:contentplaceholder) in the Master Page’s Head tag to add the Style element into the Head of your Web Form (.aspx page). However, this solution doesn’t work well when using Themes, since themes automatically include the External style sheets after the Style element – I demonstrate this and provide an alternative solution later on in this post.

The Caveat / Warnings:
In most current-generation browsers the loading order for Internal style sheets, and External style sheets depend on their position in the Head tag. This behavior seems to go against what the W3C intended.

Generally speaking we can say that all the styles will “cascade” into a new “virtual” style sheet by the following rules, where number four has the highest priority:

  1. Browser default
  2. External style sheet
  3. Internal style sheet (inside the <head> tag)
  4. Inline style (inside an HTML element)

- Taken from: http://www.w3schools.com/css/css_intro.asp

As I understand and as the w3schools point out (I can’t find a reference from the depths of the W3C), Internal style sheets should have a higher priority than External style sheets, unfortunately this isn’t the reality. Instead External style sheets and Internal style sheets depend on the loading (cascading) order. An Internal style sheet will only override an External style sheet (in current-generation browsers) if the External style sheet is loaded first. This behavior introduces problems when using an ASP Placeholder because ASP.NET automatically includes the Style Sheets (.css) from the active Theme (App_Theme) directories into the Head tag after the ASP Placeholder’s contents have been loaded.

An example of the problem:

The directory structure:

The active Master Page:
<%@ Master Language=”C#” EnableTheming=”true” AutoEventWireup=”true”
CodeFile
=”MasterPage.master.cs” Inherits=”MasterPage” %>

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
“http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>

<html xmlns=”http://www.w3.org/1999/xhtml” >
<
head runat=”server”>
<title>The Problems With Themes and Skins in ASP.NET 2.0</title>

<asp:contentplaceholder id=”ContentPlaceHolderHead” runat=”server” />

</head>
<
body>
<form id=”form1″ runat=”server”>

<h1>Hello World!</h1>

</form>
</
body>
</html>
Note: the ASP Content Place Holder between the Head tags and “Hello World!” between the H1 tags.

The default Web Form (.aspx page) providing the Content for the Master Page’s Content Place Holder:
<%@ Page Language=”C#” Theme=”Default” MasterPageFile=“~/MasterPage.master”
AutoEventWireup
=”true” CodeFile=”Default.aspx.cs” Inherits=”Default” %>

<asp:Content ID=”Content1″ ContentPlaceHolderID=”ContentPlaceHolderHead” Runat=“Server”>

<style type=”text/css”>
H1{
color: red;
}
</style>

</asp:Content>
Note: the Style element between the ASP Content Place Holder tag – H1 should now be colored red.

The contents of StyleSheet.css, the only CSS file in the Active Theme (App_Theme) directory:
H1{
color: blue;
}

Note: H1 should still be red because Internal style sheets are supposed to have priority over External style sheets.

The rendered XHTML:
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
“http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>

<html xmlns=”http://www.w3.org/1999/xhtml” >
<
head>
<title>The Problems With Themes and Skins in ASP.NET 2.0</title>

<style type=”text/css”>
H1{
color: red;
}
</style
>

<link href=”App_Themes/Default/StyleSheet.css” type=”text/css” rel=”stylesheet” />

</head>
<
body>
<form name=”aspnetForm” method=”post” action=”Default.aspx” id=”aspnetForm”>
<div>
<input type=”hidden” name=”__VIEWSTATE” id=”__VIEWSTATE” value=”…” />
</div>

<h1>Hello World!</h1>

</form>
</
body>
</html>
Note: the position of the External Style Sheet (the Link element) in relation to the Internal Style Sheet (the Style element) – the Internal style definition (
color: red;) precedes the External style definition (color: blue;).

The results in a web browser:

Note: according to the style sheet priorities in the W3C guidelines (see above) “Hello World!” should be colored red not blue – the Internal Style should be applied before the External Style; however, this is not the case.
Conclusion; the ASP Content Place Holder “Work Around” doesn’t work well with Themes since ASP.NET automatically includes all the CSS files in the active Theme directory – this behavior disrupts the loading (cascading) orders. This “Work Around” could be useful if you were only using Master Pages or were painfully meticulous with your CSS names and made heavy use of the !important style definition.

Another Solution / Another Work Around:
Define the Style element outside the Head tag, directly within the content of your page.

An example of the Work Around:
The rendered XHTML:
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
“http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>

<html xmlns=”http://www.w3.org/1999/xhtml” >
<
head>
<title>The Problems With Themes and Skins in ASP.NET 2.0</title>
<style type=”text/css”>
H1{
color: red;
}
</style>
<link href=”App_Themes/Default/StyleSheet.css” type=”text/css” rel=”stylesheet” />
</
head>
<
body>

<style type=”text/css” media=”screen”>
H1{
color: green;
}
</style
>

<form name=”aspnetForm” method=”post” action=”Default.aspx” id=”aspnetForm”>
<div>
<input type=”hidden” name=”__VIEWSTATE” id=”__VIEWSTATE” value=”…” />
</div>
<h1>Hello World!</h1>
</form>
</
body>
</html>
Note: the Style element (color: green;)inside the Body tag.

The results in a web browser:

Note: “Hello World!” is green as expected.
The Pros and Cons to this (the Style element outside the Head tag) approach:
Cons:

  1. It’s not a recommended best practice, but is used by some of the larger sites like Amazon and Yahoo!
  2. It’s not valid XHTML (but neither are iframes in XHTML Strict)

Pros:

  1. Can use Microsoft’s Conditional Comments
  2. Can use the CSS @Import rule
  3. Can use the CSS @Media rule
  4. Can use multiple CSS Media types
  5. Can easily use Media-dependent cascades
  6. Can easily control the CSS load order (inheritance and cascading)
  7. It’s fairly intuitive and understandable
  8. It’s compatible with Revision Control Systems

Conclusion; Themes are a nice addition to ASP.NET, but have some significant design flaws particularly in the way it uses CSS. Themes aren’t recommended for complex web applications that make heavy use of CSS, but for small projects they may be a nice option.

Related posts:

Author: Adam Kahtava Categories: .NET, ASP.NET, CSS, Themes and Skins Tags:
  1. No comments yet.
  1. No trackbacks yet.