Extreme ASP.NET Makeover - XHTML and CSS Improvements
By James Kovacs | 2009
Welcome back for the third installment of the multipart article series: Extreme ASP.NET Makeover. In Parts 1 and 2 , we established our development environment for improving ScrewTurn Wiki and added some acceptance tests using WatiN. This article, Part 3, will focus on using XHTML and Cascading Style Sheets (CSS) to improve the layout and visual appeal of the site.
Embracing the Web
Living in a (X)HTML World
The world of the Web is built around HTML in one form or another. Although ASP.NET Web Forms tries to protect you from the angle brackets, chances are better than not that you've spent some time looking at raw HTML. If you haven't, I would recommend devoting some time to the free introductory tutorials at w3schools.com.
Depending on your Web application, cross-browser compatibility may or may not be a concern for you. Internal enterprise applications typically only require that they run on the corporate standard browser, which is most often Microsoft Internet Explorer. At the other extreme are public Web sites that want to target the broadest audience and therefore be compatible with the broadest range of available browsers.
If you're building a public Internet site, you probably want to know which browsers are currently popular so that you can ensure that your site works properly in them. Many companies offer browser usage statistics - often for free - which can serve as a guide to currently popular browsers. As shown in Figure 1, Microsoft Internet Explorer is still the dominant browser, but Firefox makes up a substantial piece of the market. So compatibility with the major versions of those two browsers is a must for any public Internet site.
Always take browser usage statistics with a large grain of salt, because they are highly dependent on the site's target demographic. For consumer sites, the above graph is roughly representative of current browser usage as it incorporates data from a wide range of popular sites. Technical sites, such as my blog, tend to have a much higher percentage of alternative browsers, such as Firefox, Chrome, and Opera. I would expect Apple-related sites to have a much higher percentage of visits from Safari users as that is the default browser on OSX. So when deciding which browsers and operating systems to test your Web application on, you need to consider its target audience.
There are some easy things that you can do to increase the likelihood that your Web application will work across browsers. Modern browsers are designed to render HTML 4.01 and XHTML 1.0/1.1, but they do provide backward compatibility with previous HTML specifications. Browsers are typically very forgiving in their parsing of HTML and browser incompatibilities are often manifestations of the rules that a particular browser uses to parse bad HTML. For example, the following is invalid HTML and XHTML:
<p><em>The quick brown dog jumped over the lazy fox.</p></em>
Notice how the <p> and <em> overlap. Neither tag contains the other. This is invalid HTML and XHTML. Your chances of cross-browser compatibility are dramatically improved if your markup is valid HTML 4.01 or XHTML 1.0/1.1. "Valid" means that the document markup conforms to the relevant W3C specification. You can check the validity of your HTML/XHTML document using the free W3C Markup Validation Service.
Microsoft Visual Studio can also help out here as it has had a markup validation engine built in since Visual Studio 2005.
HTML/XHTML - Toe-MAY-toe/Toe-MA-toe
So what about this XHTML thing I keep writing about? What exactly is XHTML and how is it different from HTML? According to the W3C, XHTML 1.0 is "a reformulation of HTML 4 in XML 1.0". Honestly, XHTML 1.0 provides little advantage over HTML 4.01, which it supercedes, but the effort to update HTML 4.01 Web pages to XHTML 1.0 Web pages is minimal. The main advantage of XHTML is that XML parsers and tools can work with XHTML, but not with HTML. There is, purposefully, a lot of overlap between the two specifications, but the overlap isn't perfect. Let's look at the most common scenarios for turning valid HTML into valid XHTML, shown in Figure 2.
Figure 2 Common Scenarios for Turning Valid HTML into Valid XHTML
If you are building a new Web site, there is no reason not to write your markup in XHTML. If you are dealing with an existing site, you have to decide whether the effort to update existing pages to be XHTML-compliant is worthwhile. Often it is not. That said, there is no reason that new pages in an existing site cannot be written in XHTML.
WARNING: Historically, browsers were designed to parse HTML. Modern browsers have been updated to parse XHTML. Just because a browser understands that a XHTML <br/> tag is the same as a HTML <br> tag doesn't mean that it will properly interpret XML empty element tags for all XHTML elements. For example, the following is valid XHTML.
The script, test1.js, fails to run and a blank page is displayed in both Internet Explorer 8 and Firefox 3.5. Chrome 2.0 parses the XHTML correctly, running test1.js and rendering the page. The following syntactically equivalent XHTML is rendered properly by all three browsers.
So just because your page is valid XHTML and renders properly in one browser doesn't mean that it will render properly in all browsers. Your chances for success improve if the page wasn't invalid XHTML, but you still need to test in every browser and platform that you care about.
ScrewTurn Wiki is written using XHTML 1.0, which we can determine by looking at the DOCTYPE declaration in MasterPage.master:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
The DOCTYPE declaration tells the browser which version of HTML or XHTML is being used on the Web page. If you take a closer look at the DOCTYPE declaration, you'll notice it is XHTML 1.0 Transitional. The transitional part has nothing to do with XHTML per se. It is actually part of both HTML and XHTML and it relates to conformance levels. XHTML 1.0 and HTML 4.01 provide three conformance levels - strict, transitional, and frameset. Framesets are seldom used today due to problems with bookmarking and search engines. So frameset conformance is of little interest anymore. Transitional is a compatibility mode to make upgrading from prior specifications - such as HTML 3.0 - easier for existing pages. Strict is the way that the HTML/XHTML specifications were meant to be used. Strict disallows certain tags (e.g., <center>, <font>) and attributes (e.g., align, bgcolor, background) that are valid at transitional conformance. Disallowing these tags and attributes enforces better separation of structure from presentation in markup. Structure identifies the major building blocks of your page, such as a sidebar, breadcrumb trail, main heading, or article. Presentation is about how these building blocks should be rendered. For example, identifying a certain <div> tag as being the copyright notice is about structure. Noting that the <div> tag should be rendered in a x-small italic Helvetica font is about presentation. (See Roger Johansson's blog post, entitled Transitional vs. Strict Markup for a good discussion on the topic.)
So why does strict conformance disallow presentation-related tags/attributes in HTML/XHTML? It is because we now have a better mechanism for expressing presentation details... Cascading Style Sheets (CSS).
Let's Talk About CSS, Baby!
CSS or Cascading Style Sheets is a technology designed specifically to express presentation details about your Web page. Just like with HTML, I'm going to assume that you've had some exposure to CSS already. If you haven't, w3schools.com has a series of CSS Tutorials to introduce you to the technology.
Just like HTML, CSS evolved over time with CSS1, CSS2, and CSS 2.1. The CSS 2.1 specification is supported by the latest version of the major browsers including Firefox 3 and Internet Explorer 8. Unfortunately, widely used browsers such as Firefox 2.0, Internet Explorer 6, and Internet Explorer 7 do not have full CSS 2.1 support, as evidenced by the Acid2 Test from The Web Standards Project Acid Tests. Although the Acid2 Test is not going to win any art prizes, it is quite gruelling for browsers as it uses a variety of advanced CSS techniques to compose the smiley face, shown in Figure 4.
When selecting a conformance level in Visual Studio, there is no option for XHTML 1.0 Strict, as shown in Figure 3.
Figure 3 XHTML 1.0 Strict Not Listed as an Option
The reason is because the XHTML 1.1 specification eliminates the transitional and frameset conformance levels, thus implicitly only implementing strict conformance. According to the specification, its purpose is "to provide a consistent, forward-looking document type cleanly separated from the deprecated, legacy functionality of HTML 4 that was brought forward into the XHTML 1.0 document types". There are minor differences between XHTML 1.0 Strict and XHTML 1.1, but for all practical purposes the two are close enough to obviate the need for both options in Visual Studio Schema Validator.
Figure 4 Acid2 Test
Even though commonly used browsers such as Firefox 2.0 and Internet Explorer 6/7 do not render the Acid2 Test correctly, they do render most common CSS features faithfully. So as long as your stylesheets use predominantly CSS1 and commonly used CSS2/CSS2.1 features, your Web pages should render consistently across current browsers. Let's turn our attention to some recommended practices for CSS.
External Stylesheets vs. Inline Styles/Stylesheets
Styles can be included inline with a tag using the style attribute, inline with the page using a <style> tag, or in an external file with a <link> tag.
<!-- Inline style --> <div style="font-size:large">Header</div> <!-- Inline stylesheet --> <style media="all" type="text/css"> /* Styles go here */ </style> <!-- External stylesheet --> <link media="all" type="text/css" href="Site.css" />
It is a bad, though common, practice to litter your HTML/XHMTL pages with style attributes. The result is a mix of presentational with structural concerns in your Web pages. Not only does this increase the size of your Web pages, but consistent styling across the Web application is difficult as the same styles are repeated for each similar element. A small improvement can be made by moving the styling information to a stylesheet included in the <head> section via the <style> tag. Styles are no longer repeated within the page, but you still have style duplication across Web pages. Using either inline style attributes or stylesheets is not recommended. In either case, changing a site's theme or fixing an error in your CSS is very time-consuming, as every Web page in the application must be updated. More preferable are external stylesheets, so that a common set of styles can be applied uniformly throughout the Web application. This has the additional advantage of allowing the browser to cache style information rather than sending it on every page request.
Just as it is bad practice to litter your HTML/XHTML pages with style attributes, it is just as bad to define styles tightly coupled to presentation.
<div class="fontarial fontsize14 textred">Error</div>
Rather than specifying the structure of the document, CSS classes have been used to specify the presentation of the information. This is not how CSS is meant to be used. The preferred way to define this page element would be to use a CSS class to express its purpose.
The stylesheet might still use a 14px red Arial font to display errors, but notice how the structure - or intent - of the page element is expressed rather than its visual presentation.
The screen and the printed page are very different beasts. Each has its own set of layout concerns and optimizations. We have all encountered Web pages that provide a link to a "print-optimized" Web page that removes headers, sidebars, and background images. What if you could just print your Web page and have the browser optimize it for printing? Guess what? You can! CSS includes the notion of media-specific stylesheets. The styles are only applied for the specified media.
<link media="all" type="text/css" href="Site.css" /> <link media="print" type="text/css" href="PrintOnly.css" /> <link media="screen" type="text/css" href="ScreenOnly.css" />
You can include common styles in media="all" and override them for specific media in the other stylesheets. There are also media types for Braille, screen readers (aka aural), and more.
Compatibility is Easier with Valid CSS
Just like with HTML/XHTML, cross-browser compatibility of a Web application can be improved by using valid CSS. Rather than memorizing CSS specifications, you can use tools such as the W3C CSS Validation Service or Visual Studio 2008's built-in CSS Validator to ensure that not only are you writing valid CSS, but that you are only using CSS features up to a particular level, such as CSS2, but not CSS2.1, features.
Remember the "C" in CSS
An oft-forgotten feature of CSS is the cascading part - styles defined on parent tags cascade to their children. This means that you can define the font and text color for the <body> tag rather than on each individual element. (Note that cascading doesn’t make sense for some properties and hence not all properties cascade. For example, cascading the height property doesn’t make sense as all children would have the same height as the parent, which is clearly impossible for a stack of more than one child. Appendix F of the CSS2 recommendation has a full list of properties and whether child elements inherit the property from their parent.) Relying on cascading reduces duplication in your CSS and makes creating custom styles easier, as you have fewer styles to update. ScrewTurn Wiki contains a lot of duplication in its CSS. Let's see how we can simplify ScrewTurn Wiki's Default theme.
A word of warning – correct cascading of styles is often a trouble spot for older browsers. Verify the layout of your Web pages in all browsers that are important to your site.
James Kovacs is an independent architect, developer, trainer, and jack-of-all-trades living in Calgary, Alberta, specializing in agile development using the .NET Framework. He is a Microsoft MVP for Solutions Architecture and received his master's degree from Harvard University. James can be reached at firstname.lastname@example.org or www.jameskovacs.com.