Archive

Archive for the ‘CSS’ Category

The ASP.NET AJAX Learning Curve

April 9th, 2008

The ASP.NET AJAX framework comes with a lot of baggage err… I mean… a huge learning curve when compared to other AJAX Frameworks like JQuery, YUI, Dojo, Prototype / Scriptaculous.

Here's a running list of the technologies, and concepts you'll encounter when digging into ASP.NET AJAX:

  • ASP.NET
    • The Page Life Cycle
    • The Control Life Cycle
    • Web Controls
    • User Controls
    • View State
    • Session State
    • Events
  • .NET / Classical Language
    • Interfaces
    • Inheritance
    • Delegates
    • Multicast Delegates
    • Assemblies
    • Properties (Get / Set)
    • Constructors

In addition to these, you also have the technologies universal to all JavaScript libraries:

  • JavaScript:
    • Closures
    • Object Literals
    • JSON
    • Events
    • DOM Manipulation
    • Prototypical Inheritance
    • Constructors
    • XMLHttpRequest
  • Cascading Style Sheets (CSS):
  • Web Services

The ASP.NET AJAX Framework is more complex than other AJAX frameworks, I'm continually lost in it's ambiguity as it attempts to skirt around the JavaScript language – I think this learning curve (and all it's confusion) is precisely why Silverlight has so much potential.

I'm still diving into the low-level details, but my first impressions of the ASP.NET AJAX Framework are:

  • Obscure, ambiguous, no clear vision – it offers multiple (resource intensive) ways to avoid writing JavaScript, but then requires that you write JavaScript anyways
  • Too server centric
  • Too heavy weight (I'm not appreciating how they're trying to turning JavaScript into a Java, C#, .NET clone, the overhead within the browser for these conversions seems like a huge performance bottleneck)
  • Has the potential for poor performance

Most of the other AJAX libraries have been written with performance, browser responsiveness, and User Experience as their number one priorities – I'm still not sure about ASP.NET AJAX.

How many ways can we try to avoid writing JavaScript? If an AJAX library doesn't enhance the User Experience then why use it? Regardless, I'm still digging deeper.

Author: Adam Kahtava Categories: AJAX, ASP.NET, ASP.NET AJAX, CSS, DOM, JavaScript, Software 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:

Book Reviewed: JavaScript: The Definitive Guide by David Flanagan

March 26th, 2008

JavaScript: The Definitive Guide by David Flanagan is a great book! When I began reading this book I was convinced that (like many technical books) the first couple chapters would contain the important stuff and the content would slowly digress into page filler, fluff, and the book would become just another monitor stand. But not this book! After finishing the formal chapters I started reading the references – YES, this book is so good I’m reading the references! Flanagan has raised the bar for all JavaScript books – this book is in its 5th edition, and has been reviewed by a couple web Gurus (Douglas Crockford, Peter-Paul Koch).

JavaScript is the assembly language of the internet – most of the current-generation web frameworks make heavy use of JavaScript, CSS, and AJAX. If you really want to understand how ASP.NET or Ruby on Rails really works, how AJAX works, how JavaScript libraries work. If itching to push the web browser envelope, to really innovate, then this book is a required read. In addition if you’re coming from a staticly type background like Java or .NET, then JavaScript (a functional programming language) will open your eyes to a different programming model. Once you grock the fundamentals of JavaScript you’ll never be able to look at classical languages (Java, C++, .NET, …) with a straight face again. I highly recommend this book to any web developer from any web framework camp.

View my review on Amazon.

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:

How Well Do You Know JavaScript?

January 13th, 2008

JavaScript is probably the world’s most popular and misunderstood programming languages and for good reason.
When a developer claims to know JavaScript this generally equates to one or all of the following:

  • “I know what JavaScript is, I can learn JavaScript in 30 minutes
  • “JavaScript is for kids, it’s a toy language, it’s easy”
  • “I just copy and paste my JavaScript snippets / scripts from the internet”
  • “JavaScript is just another programming language like C++, C#, VB.NET, or Java”

If thoughts similar to these have crossed your mind when sizing up your JavaScript knowledge, then you probably don’t know JavaScript.

I would argue that if you’ve never programmed in a functional programming language (like: Lisp, Scheme, F#), never read a GOOD book on JavaScript, or never watched a video on JavaScript, then you probably don’t understand JavaScript at all. JavaScript is starkly different than any other mainstream programming language.

When it comes to JavaScript, if you don’t understand the fundamentals then you’re only punishing yourself.

Here are some things every JavaScript developer should probably understand:

  • JavaScript, Mocha, LiveScript, JScript, and ECMAScript are all essentially the same.
  • JavaScript is a prototypically inherited (prototype-based programming) language which is very different than the classically inherited (class-based programming) languages like C++, Java, and most of the .NET languages – you know the difference between a prototype-based programming and class-based programming language.
  • JavaScript is a loosely typed language – you know the difference between strongly-typed programming languages and weak-typed or loosely typed languages.
  • JavaScript is a functional lambda language – you understand lambdas and that functions in JavaScript can be lambdas.
  • JavaScript functions can be defined inside functions, inside functions, inside functions, and so on – you can demonstrate this.
  • JavaScript uses function scope, has no curly brace ‘{}’ block scope – you understand that this is common attribute of most functional programming languages.
  • JavaScript has no private, public, protected assessors, no classes, no enums, no structs – you understand that all these language features can be achieved through objects and function closures.
  • JavaScript is classless, but instead it uses objects as general containers.
  • JavaScript makes use of garbage collection.
  • JavaScript uses truthy and falsy values – you understand which values are truth and falsy.
  • JavaScript makes use of the ‘nan’ (not a number) and ‘undefined’ values – you understand the difference between these values.
  • JavaScript has pretty good debuggers – you understand how to debug JavaScript from both IE (link) and Firefox (link).
  • You appreciate recursion, and understand that recursion is a useful technique in JavaScript.
  • You understand that JavaScript Namespaces should be used – you understand the importance of namespaces, and know how to create one (Namespacing Your JavaScript).
  • You know how to avoid the JavaScript pseudo-protocol (<a href=”Javascript:alert(‘hello’);”), and appreciate avoiding it.
  • You know how to avoid embedding DOM Level 0 JavaScript events (<a onclick=”alert(‘hello’);”) in your mark-up / document structure, and appreciate this technique.
  • You know that JavaScript can make use of two different event models (event capturing and bubbling), but we should only ever make use of bubbling.
  • You understand what JSON is and how it’s used.
  • You know how to keep you JavaScript, CSS, document structure separate, and appreciate non obtrusive JavaScript.

If any of these points seem foreign, then it may be time to learn JavaScript. With all the hype and buzz around Web 2.0 and AJAX it could be a great way to augment your career while broadening your programming language vocabulary.

Great resources for learning more about JavaScript:

Videos:

Books:

Links:

Author: Adam Kahtava Categories: .NET, AJAX, ASP.NET, CSS, DOM, Firefox, IE, JavaScript, Software, Videos Tags:

My first Greasemonkey Script: Goodbye ASP.NET Forum Ads

November 21st, 2007

Greasemonkey is an add-on for Firefox. Through JavaScript it allows anyone the ability to dynamically modify a page as, or after it’s being rendered in the browser. This lets anyone trim the DOM, remove ads, and modify page in anyway they see fit (it also opens up some serious privacy concerns with XSS). Anyhow, I spend a fair time on the ASP.NET forums, but the advertisements have always made for a somewhat negative, but tolerable user experience.

Today I finally broke down and wrote my own Greasemonkey script – now formally known as “The ASP.NET Forums Beautifier” for lack of a better name.

The Script Before and After:

Before – usually the ASP.NET Forums look like this:

After – with my script running in Greasemonkey we get this:

note: the greasemonkey icon, and complete lack of fluff / advertisements on the second screenshot.

Creating this script was simpler than I expected. It was a matter of skimming through an article on How to write Greasemonkey scripts, using Firebug’s JavaScript Console and Firefox’s Error Console to test my code (after all, Firefox is the new IDE, Firefox as an IDE), and an hour later, Viola! No more ads.

The YUI blog and Douglas Crockford in particular, have inspired my JavaScript renaissance. JavaScript is really interesting, it’s a functional, loosely typed programming language that uses prototype-base inheritance. Developing in JavaScript is a real treat from some of the more statically typed languages.

Download Greasemonkey and “The ASP.NET Forums Beautifier” for yourself. :)

Author: Adam Kahtava Categories: CSS, DOM, Firebug, Firefox, JavaScript, greasemonkey 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: