Archive

Archive for the ‘Themes and Skins’ Category

The Good Parts of The ASP.NET Framework and Visual Studio

May 31st, 2008

Douglas Crockford opens his latest book with these words:

Most programming languages contain good parts and bad parts. … [the language designers or architects] are usually powerless to do anything except heap more features on top of the existing pile of imperfections. And the new features do not always interact harmoniously, thus producing more bad parts. – JavaScript: The Good Parts by Douglas Crockford

His words can apply to all programming languages and frameworks. Like the Microsoft .NET Framework, Visual Studio, Java, and Eclipse.

Bad parts in the ASP.NET Framework and Visual Studio:

  • ASP.NET Themes and Skins
  • The ASP.NET AJAX Framework
  • ASP.NET / Visual Studio Inline Style Properties
  • Visual Studio Design View
  • ASP.NET and Visual Studio’s over dependency on XML configuration files

It would be great if someone wrote a book outlining the good parts of ASP.NET and Visual Studio. :)

Author: Adam Kahtava Categories: ASP.NET, JavaScript, Musings, Themes and Skins Tags:

A Reflection on Themes, Skins, and Cascading Style Sheets (CSS) in ASP.NET 2.0 (A Final Conclusion)

April 7th, 2008

A couple years ago I was thrown into a web application that made heavy use of ASP.NET Themes and Skins. Prior to this I depended exclusively on Cascading Style Sheet (CSS) for my web development / web design needs. A first glance at ASP.NET Themes and Skins looked promising, but a number of flaws surfaced – see the links and issues listed at the end of this post.

In addition to these issues, here are a couple other considerations when thinking about ASP.NET Themes:

  • Themes do not adequately separate the levels of concerns within your application. When using Themes all design related files are baked into the application. From a maintainability standpoint, this doesn’t bode well in large web applications. Hosting design related files on a single server or an external Content Delivery Network (CDN) is an effective way for managing site wide UI updates and increasing a sites performance, ASP.NET Themes works against this technique.
  • Themes add unneeded complexity by obscuring the real technologies at work (CSS). Everything that ASP.NET Themes offer can be better achieved outside of the ASP.NET Theme Framework. Technologies like Cascading Style Sheets (CSS),  alternate Style Sheets, and JavaScript can achieve more than Themes can provide.
  • Themes are a server-side mechanism. Themes become a nuisance in client-side dependent, heavily dynamic, Web 2.0, DHTML, AJAX type web applications.
  • Themes discourage developers from learning more about web design and the technologies surrounding it. Themes offer a seemingly simple API, which shelters developers from the complexities of CSS and JavaScript, but sooner or later The Law of Leaky Abstractions comes into play and knowing the fundamentals of these technologies is a necessity.
  • Professional web designers don’t use ASP.NET Themes, CSS is the language of web designers.

Default Skins on the other hand can be useful for defining consistent CSS hooks into common ASP.NET controls. It’s unfortunate that we can’t use Skins without Themes.

Related posts:

Author: Adam Kahtava Categories: .NET, ASP.NET, CSS, Themes and Skins Tags:

Free: Win a Copy of Professional ASP.NET 2.0 Design: CSS, Themes, and Master Pages

February 25th, 2008

Professional ASP.NET 2.0 Design: CSS, Themes, and Master Pages by Jacob Sanford is a great book for ASP.NET developers looking to expand their knowledge on the ASP.NET 2.0 Web Design front.

I've read this book, re-read it, edited it, and would like to give it away – I was the Technical Editor. The books is like new and (did I mention) it's free!

Contest Rules:

  • Updated! Just Leave a comment with a valid email address!
  • Post a 500 x 200 pixel image of something you're working on in the comments of this post – this image could be code, web design, or anything work related.
  • Include an optional description of your work
  • The winner will be chosen April 1st May 1st, they'll be drawn at random, and will be notified through email.
  • I pay for shipping.

* I've included a sample entry in the comments. If you're looking for a great free photo editing application then try Paint.net. If you're looking to host your image you might want to consider Flickr or Photobucket.

Good Luck!

The contest has ended, and the winner is….. Andrew Hinde. Nice!

Author: Adam Kahtava Categories: .NET, ASP.NET, Book, CSS, Contest, Themes and Skins Tags:

A Resolution to The Problems with Themes, Skins, and Cascading Style Sheets (CSS) – Putting the Cascades back into ASP.NET 2.0 Themes (taking control over CSS Cascades / Load Order, Media Types, and Overrides)

April 2nd, 2007

ASP.NET 2.0 Themes have a couple design flaws, all of which center around the way Themes reference Cascading Style Sheets (CSS). I’ve been posting Theme and CSS related issues and work arounds as I encountered them, and in one of my first posts I outlined the possibility of using a VirtualPathProvider to ignore the CSS files within a directory. In this post I share David Marzo’s implemented of this solution. This resolution resolves most of the issues surrounding Themes and CSS, and essentially puts the Cascades back into CSS.

The Problem / Question:
ASP.NET 2.0 Themes automatically includes all the Style Sheets (.css files) found in the active Theme (App_Theme) directory into the Head of the rendered document. This severely limits the robust CSS language, and works against the last decade of Cascading Style Sheet progress. For more specific details on the problems with ASP.NET 2.0 Themes start reading the articles found here.

A Solution / Work Around:
Add a custom VirtualPathProvider to ignore the Style Sheets (CSS files) found in the App_Theme directory. For more background on this solution see my article and David Ebbo’s article titled Overriding ASP.NET combine behavior using a VirtualPathProvider.

An example of the problem:

The directory structure:

Notice all the Style Sheets (.css files), there are more in the Adapters directory too.

Before including the CustomVirtualPathProvider (code provided below) into the project’s build – the XHTML rendered by Themes:

<html xmlns="http://www.w3.org/1999/xhtml" >
  <head><title>The Problems With Themes and Skins in ASP.NET 2.0</title>
    <link href="App_Themes/Default/CSS/Adapters/ChangePassword.css" type="text/css" rel="stylesheet" /> 

    ... The other 17 externally linked Style Sheets go here, they were removed to improve readability ...

     <link href="App_Themes/Default/CSS/PrinterFriendly.css" type="text/css" rel="stylesheet" />
  </head>
<body>

The Style Sheets are automagically inserted into the Head tag from the active Theme directory. Keep in mind that Internet Explorer has a 30 Style Sheet limitation (see article Q262161).

After including the CustomVirtualPathProvider (code provided below) into the project’s build – the XHTML rendered by Themes:

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

Notice the complete lack of Style Sheets – ahhh simplicity is bliss, the very foundations of CSS Zen Enlightenment… :) Now we can manually include our Style Sheets, use Conditional Comments, and so on.

The source code for the CustomVirtualPathProvider provided by David Marzo in C#:

namespace Arfila.Web.Logic {
 
 [AspNetHostingPermission(SecurityAction.Demand,
   Level = AspNetHostingPermissionLevel.Medium)]
 [AspNetHostingPermission(SecurityAction.InheritanceDemand,
   Level = AspNetHostingPermissionLevel.High)]
 public class CustomVirtualPathProvider : VirtualPathProvider {
 
   public static void AppInitialize() {
     HostingEnvironment.RegisterVirtualPathProvider(new CustomVirtualPathProvider());
   }
 
   public CustomVirtualPathProvider() : base() { }
 
   private bool IsThemeDirectory(string virtualPath) {
     String checkPath = VirtualPathUtility.ToAppRelative(virtualPath);
     return checkPath.StartsWith("~/App_Themes/", 
       StringComparison.InvariantCultureIgnoreCase);
   }
 
   public override VirtualDirectory GetDirectory(string virtualDir) {
     if (IsThemeDirectory(virtualDir)) {
       return new ThemeDirectory(Previous.GetDirectory(virtualDir));
     }
     else {
       return Previous.GetDirectory(virtualDir);
     }
   }
 }
 
 [AspNetHostingPermission(SecurityAction.Demand,
   Level = AspNetHostingPermissionLevel.Minimal)]
 [AspNetHostingPermission(SecurityAction.InheritanceDemand,
   Level = AspNetHostingPermissionLevel.Minimal)]
 public class ThemeDirectory : VirtualDirectory {
 
    VirtualDirectory _toFilter;
    private ArrayList _children = new ArrayList();
    private ArrayList _directories = new ArrayList();
    private ArrayList _files = new ArrayList();
 
    public override IEnumerable Children {
      get { return _children; }
    }
 
    public override IEnumerable Directories {
      get { return _directories; }
    }
 
    public override IEnumerable Files {
      get { return _files; }
    }
 
    public ThemeDirectory(VirtualDirectory toFilter) : base(toFilter.VirtualPath) {
      _toFilter = toFilter;
      BuildChild();
    }
 
    private void BuildChild() {
      foreach (VirtualDirectory dirToFilter in _toFilter.Directories) {
        ThemeDirectory themeDir = new ThemeDirectory(dirToFilter);
        _children.Add(themeDir);
        _directories.Add(themeDir);
      }
 
      foreach (VirtualFile fileToFilter in _toFilter.Files) {
        string fileExtension = VirtualPathUtility.GetExtension(fileToFilter.VirtualPath).TrimStart('.');
        if (string.Compare(fileExtension, "css", true) != 0) {
          _children.Add(fileToFilter);
          _files.Add(fileToFilter);
        }
        else {
          //archivo .css no incluir
        }
      }
    }
  }
}

Some of the code has been modified for readability, download the original source code here.

Note: In order to use this VPP you’ll have to copy the code above into a new class in your App_Code directory.

Caveat: If a Web site is precompiled for deployment, content provided by a VirtualPathProvider instance is not compiled, and no VirtualPathProvider instances are used by the precompiled site. – Taken from the article titled VirtualPathProvider Class on MSDN.


Conclusion:
This is one of the nicest work arounds or resolution to the issues surrounding ASP.NET 2.0 Themes. It allows us to leverage the power of ASP.NET 2.0 default Skins, allows us to logically group design related resources (Style Sheets, images, default Skins, videos, etc…) in the App_Theme directory, allows us to control the loading order (cascades) of style sheets, allows us to use Conditional Comments, to define Media Types, to override / inherit Styles, and to continue using CSS as it’s intended. In addition we can now easily integrate the ASP.NET 2.0 CSS Friendly Control Adapters into our web applications.

Author: Adam Kahtava Categories: .NET, ASP.NET, CSS, Themes and Skins Tags:

In Favor of Using Style Elements / Embedded Style Sheets / Style Blocks / Style Tags or Whatever You Want To Call Them inside the HTML / XHTML Body.

March 20th, 2007

I’ve been using Style Elements within the HTML Body tag to work around some of the design flaws presented in ASP.NET 2.0 Themes – see the second solution in this post for more details. I’ve been leary of using this method because it’s not a best practice, since it compromises the validity of the HTML / XHTML document. I decided to do a little more research on this subject and made the following discoveries.

Discoveries:

  1. Some of the more complex web sites (Amazon and Yahoo!) make use of Style Elements within the Body Element – see the source snippets below.
  2. Gecko (Firefox, Flock, Mozilla, etc…) based browsers automatically move Style Elements found within the Body Element into the Head Element and render the page as expected – see the rendered Document Object Model (DOM) image below.
  3. Internet Explorer doesn’t move the Style Element into the Head Element, but renders the page as expected.
  4. Opera… well I wish I knew what Opera did, but the page renders as expected.

Source snippet from Amazon:

</table>
    </td>
  </tr>
</table

<style type=”text/css”>
.lol-hr-center { margin: 5px; border-top-width: 1px;
/* and so on… */
}
</style>

<div id=”listoflists_data” style=”display:none”>
Note how the Style element is located between the <table> and <div> tags.


Source snippet from Yahoo!:

<h4>
<
a id=”paweather” class=”details” href=”r/wb/*-http://weather.yahoo.com/forecast/USKS0448_f.html”><span class=”icon”>Weather <b><strong>51&deg;</strong>F</b></span></a>

<style type=”text/css”>#patabs #weather .icon{background:url(http://us.i1.yimg.com/us.yimg.com/i/us/we/31/b/26.gif) 3px 2pxno-repeat;}</style>

</h4>
Note how the Style element is located within the <h4> tag.

A snapshot of the Document Object Model (DOM) as seen through Firebug:


Note the highlighted area references the Yahoo! source snippet from above.
Conclusion: Although the Style Element within the Body Element compromises the validity of a document, some of the leaders in web design and accessibility use this approach, so it may not be as big a work around or hack.

Author: Adam Kahtava Categories: .NET, ASP.NET, CSS, DOM, Firebug, Firefox, IE, Opera, Themes and Skins Tags:

The Problems with Themes, Skins, and Cascading Style Sheets (CSS) in ASP.NET 2.0 – Creating Printer Friendly Pages (defining a CSS Print Media Type) with CSS While Using Themes (Work Around #5)

February 25th, 2007

In this post I outline a couple alternate ways of defining the CSS Print Media Type with Themes. ASP.NET 2.0′s Themes and Skins have a number of design flaws – Themes and Skins depend almost entirely on Cascading Style Sheets (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 use the CSS Print Media Type with Themes? In the past I’ve used an External Style Sheet which defined the Print Media Type, but ASP.NET 2.0 omits the Media Type attribute when it automatically includes all my CSS files (from the active Theme directory) into the HTML Head tag.

A Solution / Work Around:
The Print Media Type isn’t constrained to External Style Sheets and can be defined in the Style Element, in the @Media rule, and even specified through the @Import rule.

An example of the problem:

The directory structure:

The rendered XHTML:
<head>
<title>The Problems With Themes and Skins in ASP.NET 2.0</title>
<link href=“App_Themes/Default/PrinterFriendlyStyleSheet.css”
type=”text/css” rel=”stylesheet” />
<link href=“App_Themes/Default/StyleSheet.css”
type=”text/css” rel=”stylesheet” />
</head>
Note each externally linked Style Sheet lacks a media type.

Our desired XHTML (using an Externally Linked Style Sheet and a Print Media Type) would have looked something like this:
<head>
<link href=“App_Themes/Default/PrinterFriendlyStyleSheet.css”
type=”text/css” rel=”stylesheet” media=”all” />
<link href=”App_Themes/Default/PrinterFriendlyStyleSheet.css”
type=”text/css” rel=”stylesheet” media=”print” />
</head>
Note the Media Type (media=”print”) in bold.

The solutions:

Option 1. Use the Media Rule (@Media) to define the print Media Type inside an Externally Linked Style Sheet.

An example:
@Media Print {
body {
background-color: #FFFFFF;
}
/*… your CSS here …*/
#Menu, #AdvertismentContainer {
display: none;
}
#Content {
width: 100%;
}
}
Discussion: This is probably the best alternative to defining the Media Type in an Externally Linked Style Sheet – the other solutions introduce problems of their own.

Option 2. Use the Import Rule (@Import) to load your printer friendly Style Sheet from an alternate location and define a Media Type – this involves removing your printer friendly Style Sheet from the Themes (App_Theme directory).

An example:
@Import url(“/AppName/CSS/PrinterFriendlyStyleSheet.css”) Print;

Discussion: This solution requires moving our Printer Friendly Style Sheet outside the Theme directory, since Themes don’t allow us to exclude a Style Sheet folder (see Excluding a CSS folder for more details). Once we start moving Style Sheets outside the Themes directory we should probably ask ourselves why we’re even using Themes, and consider regaining complete control over our CSS by moving all the CSS files outside the Theme directory. At this point we could revert to Externally Linking our Style Sheets where we could define our Media Type attributes. In addition the CSS URL function used in this solution confuses many.

Option 3. Use the Style Element to define a Print Media Type.

An example:
<style type=”text/css” media=“print”>
/*… your CSS here …*/
</style>

Discussion: This solution doesn’t work if the Style Elements are defined in the HTML head (see Using Internal (Embedded) Style Sheets with Themes for more details), you can however move the Style Element into the Body of the document, this compromises the HTML validation, but large e-commerce sites like Amazon and Yahoo! make heavy use of this method.

Option 4. Sub class the HtmlHead class to enumerate through the child controls and add new Meta attributes to the child controls using the HtmlLink class. See my post titled Defining a Media Type(s) for more details.
Discussion: This solution requires a fair amount of work and only solves one of the many problems with Themes, pursuing this solution would probably be a case of not seeing the forest for the trees.

In conclusion; Themes are a nice addition to ASP.NET, but have some significant design flaws particularly in the way it uses CSS – in this case how printer friendly (print) CSS Media Types are defined. I wouldn’t recommend using Themes on a complex web applications that make heavy use of CSS or AJAX, but for small projects they may be a nice option.

Related links:

Related posts:

Author: Adam Kahtava Categories: .NET, ASP.NET, CSS, Themes and Skins Tags:

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:

The Problems with Themes, Skins, and Cascading Style Sheets (CSS) in ASP.NET 2.0 – Defining the Load Order (Cascades) for CSS (Work Around #3)

February 3rd, 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:
Is it possible to define the loading order (cascades) of CSS files while using Themes in ASP.NET 2.0?

The Solutions / Work Arounds:
Order your CSS files alphanumerically – ASP.NET 2.0 parses through the active Theme directory and all sub directories alphanumerically including every CSS file into the HTML head (via an external link) of the rendered page.

An example of the problem (when load order isn’t defined).
Note: both examples use the same CSS files, but use different loading orders.

The directory structure and StyleSheets:

The rendered XHTML:
<html xmlns=”http://www.w3.org/1999/xhtml”>
<
head>
<title>The Problems With Themes and Skins in ASP.NET 2.0 </title>
<link href=”App_Themes/Default/Controls/OverloadedUserWebControlStyleSheet.css
type=”text/css” rel=”stylesheet” />
<link href=”App_Themes/Default/Controls/ReusedUserWebControlStyleSheet.css
type=”text/css” rel=”stylesheet” />
<link href=”App_Themes/Default/OverloadedStyleSheet.css
type=”text/css” rel=”stylesheet” />
<link href=”App_Themes/Default/ReusedStyleSheet.css
type=”text/css” rel=”stylesheet” />
</
head>

The results in a web browser:

An example of the problem (when load order has been defined alphanumerically).

The directory structure and StyleSheets:

Note: the use of alphanumeric delimiters preceding the Style Sheet names.

The rendered XHTML:
<html xmlns=”http://www.w3.org/1999/xhtml”>
<
head>
<title>The Problems With Themes and Skins in ASP.NET 2.0 </title>
<link href=”App_Themes/Default/aa_ReusedStyleSheet.css
type=”text/css” rel=”stylesheet” />
<link href=”App_Themes/Default/Controls/01_ReusedUserWebControlStyleSheet.css
type=”text/css” rel=”stylesheet” />
<link href=”App_Themes/Default/Controls/09_OverloadedUserWebControlStyleSheet.css
type=”text/css” rel=”stylesheet” />
<link href=”App_Themes/Default/zz_OverloadedStyleSheet.css
type=”text/css” rel=”stylesheet” />
</
head>

Note: the ordering of the CSS files.

The results in a web browser:

Comparing the web browser results:

The Pros and Cons to this approach:

Cons:

  1. Being a work around it’s not intuitive _ a maintenance programmers nightmare – “I’m familiar with CSS, but how are the Cascading Style Sheets being loaded??”
  2. Contributes to a fragile environment – the way ASP.NET parses through the App_Themes directories may change in newer versions of ASP.NET, not to mention changing a filename could have negative side effects on the site’s design.

Pros:

  1. Allows a load order to be defined
  2. Compatible with Revision Control Systems

In 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:

The Problems with Themes, Skins, and Cascading Style Sheets (CSS) in ASP.NET 2.0 – Defining a Media Type(s) (Work Around #2)

November 11th, 2006

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 classes or IDs.

The Problem / Question:
Is it possible to define CSS Media types (like media=”print”) in the HTML Head tag? ASP.NET 2.0 automatically includes all my CSS files (from the active Theme directory) into the HTML Head tag, but Themes don’t allow me to specify any CSS Media types.

The Solutions / Work Arounds:
Sub class the HtmlHead class to enumerate through the child controls and add new Meta attributes to the child controls using the HtmlLink class. In order to use multiple Media types you would probably need to use more complex logic and resolve Media types to filenames (i.e. SomeFileName_Print.css could resolve to media=”print”) – for more information on manipulating the HtmlHead class read Phil Scott’s post titled: Accessing the Html Header in ASP.NET 2.0.

An example of the problem:
The HTML source automatically generated by ASP.NET 2.0 Themes (note the lack of media attributes):
<head>
<title>The Problems With Themes and Skins in ASP.NET 2.0 </title>
<link href=”App_Themes/Default/HandHeld.css”
type=”text/css” rel=”stylesheet” />
<link href=”App_Themes/Default/Print.css”
type=”text/css” rel=”stylesheet” />

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

</head>

My desired HTML source (note the media attributes in bold):
<head>
<title>The Problems With Themes and Skins in ASP.NET 2.0 </title>
<link href=”App_Themes/Default/Default.css”
type=”text/css” rel=”stylesheet” media=all />
<link href=”App_Themes/Default/HandHeld.css”
type=”text/css” rel=”stylesheet” media=handheld />
<link href=”App_Themes/Default/Print.css”
type=”text/css” rel=”stylesheet” media=print />
<link href=”App_Themes/Default/Screen.css”
type=”text/css” rel=”stylesheet” media=screen />
</head>

The Pros and Cons of this approach:

Cons:

  1. Can’t use Microsoft’s Conditional Comments
  2. Can’t use the CSS @Import rule
  3. Can’t use the CSS @Media rule
  4. Can’t easily use multiple CSS Media types
  5. Can’t easily control CSS preferred and alternate style sheets
  6. Can’t easily control the CSS load order (inheritance and cascading)
  7. Contributes to a fragile environment
  8. Not intuitive _ a maintenance programmers nightmare – “I know CSS, but Where are the Media types defined and How are they controlled?”

Pros:

  1. Can define a single Media type for all .css files relatively easy
  2. Could define multiple Media types – with more complex logic dependant on .css file naming
  3. Could control CSS preferred and alternate style sheets – with more complex logic dependant on .css file naming
  4. Compatible with Revision Control Systems (CVS, Subversion, Visual Source Safe, and so on)

In conclusion; CSS will continue to be the industry design standard – it has been the standard for well over 10 years. CSS is far more powerful than Themes and Skins, I suggest sticking with CSS and perhaps using some default Skins that define CSS classes or IDs.

Related posts:

Author: Adam Kahtava Categories: .NET, ASP.NET, CSS, Themes and Skins Tags:

The Problems with Themes, Skins, and Cascading Style Sheets (CSS) in ASP.NET 2.0 – Excluding a CSS folder (Work Around #1)

November 9th, 2006

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 classes or IDs.

The Problem / Question:
How can I exclude a subdirectory (sub folder) containing Cascading Style Sheets (CSS) in a Theme (App_Theme) directory? ASP.NET 2.0 automatically includes all CSS files (.css) from the active Theme directory and sub directories into the rendered HTML page, but doesn’t allow me to exclude a folder of CSS files or a single CSS file.

The Solutions / Work Arounds:

  1. Create your CSS directory outside the App_Theme directory then map a Virtual Directory inside your Theme directory.
  2. Add a custom VirtualPathProvider to ignore the non-root level CSS files in sub directories  – See David Ebbo’s article titled: Overriding ASP.NET combine behavior using a VirtualPathProvider.

These “Work Arounds” are useful if you want to do something like this (note: Default.css is sitting in the root of the active Theme directory):

/* Default.css */
@ImportStyleSheets/Common.css “;
@ImportStyleSheets/Masterpage.css”;
<!–[if IE]>
@Import “StyleSheets/FixInternetExplorer_Quirks.css”;
<![endif]–>
<!–[if IE 7]>
@Import “StyleSheets/FixInternetExplorer7Quirks.css”;
<![endif]–>

Or if you wanted to use an Embedded CSS Statement like this:

<style type=”text/css”>
<!
@Import “StyleSheets/HideNavigation.css”;
@Import “StyleSheets/HideSearchBars.css”;
>
</style>

The Pros and Cons of this approach:

Cons:

  1. Can’t really define CSS media types, but we can now use the CSS @Media rule
  2. Can’t control CSS preferred and alternate style sheets
  3. Doesn’t scale well
  4. Contributes to a fragile development environment
  5. Not very compatible with Revision Control Systems (CVS, Subversion, Visual Source Safe, and so on)
  6. Not intuitive _ a maintenance programmer’s nightmare, “I know CSS, but Where is the CSS folder?” or “I know CSS, but Why and How are some CSS folders excluded?

Pros:

  1. Can control the load order (inheritance and cascading) through the CSS @Import rule
  2. Can exclude a folder containing CSS files
  3. Can use the CSS @Import rule
  4. Can use the CSS @Media rule
  5. Can use Microsoft’s conditional comments


In conclusion;
CSS will continue to be the industry design standard – it has been the standard for well over 10 years. CSS is far more powerful than Themes and Skins, I suggest sticking with CSS and perhaps using some default Skins that define CSS classes or IDs.

Related posts:

Author: Adam Kahtava Categories: .NET, ASP.NET, CSS, Themes and Skins Tags: