ASP.NET 2.0

Enforce Web Standards For Better Accessibility

Ben Waldron

This article discusses:

  • Adopting Web standards
  • CSS Control Adapters
  • ASP.NET 2.0 Themes and Master Pages
This article uses the following technologies:
ASP.NET 2.0

Code download available at: Web Standards 2007_04.exe(318 KB)

Contents

Adopting Web Standards
XHTML Flavors
ASP.NET 2.0 as a Web Standards Platform
CSS Control Adapters
Master Pages and Themes
The Petition

I have to admit that Web standards were not always very important to me. Like many of you, I began writing Web pages at the time the first Web browsers were being released. Back then, I thought closing every HTML paragraph tag would slow me down and consume unnecessary portions of a user's precious 28K of bandwidth. So, I didn't do it. As long as the browser didn't care, neither did I.

Since then, however, I have begun to recognize the importance of Web standards to the future of the Web and of Web-based software in general. Of course, Web standards are about much more than closing HTML tags. They are a critical factor in how well software components can be used in future contexts.

Besides complying with the W3C standards for XHTML, cascading style sheets (CSS), XML, and so forth, Web applications should be search-engine friendly, accessible, have human-readable URLs, and employ other accepted practices that make them easier to find and use. Web standards also require careful attention to the structure of the code behind the sites, making it easier to maintain in the future. In this article I'll explain why everyone, especially those writing server controls, should adhere to Web standards.

Adopting Web Standards

Web standards impact four broad categories: code validity, site navigation, accessibility, and separation of content and design, as shown in Figure 1. If you address the larger concerns in these categories, the job of producing standards-compliant code is largely accomplished. Let's look at each category in turn.

Figure 1 Categorizing Web Standards

Standard Description
Code validity Web sites must use valid XHTML and CSS according to W3C standards and be well formed. This will ensure maximum browser support, faster rendering, and code that's easier to understand.
Site navigation Web sites should have a hierarchic structure with a site map and user-friendly URLs. Users should be able to determine their location within a site based on the URL.
Accessibility Web sites must be available to impaired users and should be available across a wide range of browsers and devices.
Separation between design and content Web sites must use a style sheet to define layout and presentation with content represented in XHTML.

XHTML and jigsaw.w3.org/css-validator for CSS. These services can be automated as part of your build process or performed manually before code is deployed.

Most browsers are evolving to adhere to Web standards. This is certainly true of Internet Explorer® 7.0 and Mozilla Firefox 2.0, which were released at the end of 2006. So when you stick to the Web standards they enforce, you can be much more confident that your code will render correctly on current browsers.

Site Navigation Many content management systems internalize content and serve up page URLs that give the user no clue about where the page is in relation to the rest of the site. Moreover, dynamically created content tends to generate unfriendly URLs because information such as unique identifiers is often passed in the URL via the query string. To remedy these problems, URLs should be organized according to subject matter and show the user where he is. And you can achieve friendly URLs for dynamically generated content by using URL rewriting, in which an HTTP module maps an unfriendly URL to a friendly URL when the HTTP request is handled. URL rewriting is supported in the Microsoft® .NET Framework. Friendly URLs also make your content more discoverable, and some search engines actually rank pages higher if they have friendly URLs.

Accessibility Building or rendering code that is accessible to people with disabilities is as important to a business as building wheelchair-accessible doors. You can't possibly predict the abilities of all the users who will visit your site. For example, between five and ten percent of all males are colorblind. Fortunately, there are a few easy practices that can make a Web site more accessible. Avoiding the use of tables can help because screen readers, which read the screen to visually impaired users, are confused by table layouts. Accessible forms are important as well. I am guilty of building a two-column table with one column containing the label and the other containing the HTML form element. The correct approach is to define a label with the "for" attribute indicating the ID of the form element that the label describes (see Figure 2).

Figure 2 An Accessible Form

<form id="FormAccessible" runat="server">
    <fieldset>
        <legend>Personal Information</legend>
        <p>
            <label for="TextFirstName">First Name</label> 
            <asp:TextBox ID="TextFirstName" runat="server" 
                AccessKey="f" TabIndex="0" />
        </p>
        <p>
            <label for="TextLastName">Last Name</label> 
            <asp:TextBox ID="TextLastName" runat="server" 
                AccessKey="l" TabIndex="1" />
        </p>
    </fieldset>
    <fieldset>
        <legend>Contact Information</legend>
        <p>
            <label for="TextEmail">Email</label> 
            <asp:TextBox ID="TextEmail" runat="server" 
                AccessKey="e" TabIndex="2"/>
        </p>
    </fieldset>
</form>

Other accessibility approaches include choosing easily distinguishable colors for important items like links and buttons, making sure that pages are readable when font size is increased (and allowing it to be increased), and using the alt attribute to describe images. A nice side-effect of using alt is that the description can be indexed by search engines.

Finally, designing the site to be more device-agnostic means more people can access it. After all, users have cell phones, PDAs, Smartphones, and other devices that access the Web. It is frustrating for them not to be able to access the data they need because the site can't be consumed on a mobile device.

Separation of Content and Design Web pages were around long before XML became the ubiquitous standard it is today. With XML, there is a clear distinction between content and design because XML doesn't easily allow style information to be intertwined with content the way HTML did.

The benefits to this separation are many. Keeping all layout and style information in CSS stylesheets makes it possible to support multiple devices. It makes the emitted XHTML smaller. The XHTML is cleaner and more organized, which is good for editing and debugging. Cleaner XHTML also makes it easier for screen readers to read the contents of a Web page and allows search engines to more accurately index the pages.

XHTML Flavors

Now that I've highlighted the importance of Web standards, let's create some pages that implement them. The first step is to choose the correct document type. The document type definition (DOCTYPE) tells the browser's validator which type of XHTML you are using. XHTML 1.0 comes in three flavors: Strict, Transitional, and Frameset. XHTML 1.1 provides only one flavor that restricts the use of HTML elements that are deemed presentational. The types are listed in Figure 3.

Figure 3 XHTML Document Types

Version Syntax Description
XHTML 1.0 Strict <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict //EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> Supports only elements and attributes defined in HTML 4.01 and follows XML syntax rules.
XHTML 1.0 Transitional <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional //EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> Supports some deprecated elements and attributes that are considered presentational (such as <center> and <u>).
XHTML 1.0 Frameset <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset //EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"> Supports the use of frames using the <object> or <iframe> elements. In general, the use of iframes is discouraged.
XHTML 1.1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1 //EN" "https://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> Most recent W3C recommendation, removes all elements considered presentational.

It's better to use the XHTML 1.1 or HTML 1.0 Strict DocTypes because they help ensure that all presentational elements migrate away from the XHTML and into style sheets. Note, however, that conforming to these types does not completely ensure that a page is Web standards-compliant because the use of XHTML tables to position content is still permitted; therefore, you can't rely completely on validation since validation won't fail simply because you use tables.

The Transitional DocType should be used when you can't completely eradicate all presentational elements from code. It should be used to signal that the page is not strictly compliant and needs to be refactored at a later time.

Frames are supported by the XHTML 1.0 specification, but were removed for XHTML 1.1. In the future, the use of iframes and objects will likely be replaced by the XFrame specification. Including frames has been generally discouraged because of usability concerns. If you've ever hit the Back button on a Web page that has frames, you know what I mean.

ASP.NET 2.0 as a Web Standards Platform

There were some well-known deficiencies in ASP.NET 1.1. The out-of-the-box controls produced code that would not pass validation. That was largely attributed to the way that ViewState was handled in ASP.NET 1.1-using a hidden input tag that was not contained within a block display, like this:

<input type="hidden" name="__VIEWSTATE" 
value="dDwtMTU1NzQzNDgy..." />

This, combined with some other syntactical issues, gave ASP.NET 1.1 an unfortunate reputation for non-compliance.

ASP.NET 2.0 addressed many of the Web standards issues. For example, if you look at the source of ASP.NET 2.0-generated pages, you see that ViewState is now wrapped in a div tag, making it compliant:

<div>
    <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" 
           value dDwtMTU1NzQzNDgy..." />
</div>

Microsoft has made it known publicly that one of the goals of ASP.NET 2.0 is to be more aligned with Web standards and, in fact, ASP.NET 2.0 lets you create compliant Web sites and controls. A great resource for building compliant Web sites is Stephen Walther's MSDN® article "Building ASP.NET 2.0 Web Sites Using Web Standards". This 78-page article goes into great detail on building sites according to Web standards.

CSS Control Adapters

While ASP.NET 2.0 takes a great step forward in terms of compliance, there are still challenges. For instance, some ASP.NET 2.0 controls render as HTML tables when they shouldn't. In some cases, controls like a GridView or DataList should render output within a table since the nature of the control dictates tabular data. Other controls, like the menu control, should not render as a table. Figure 4 shows a portion of an HTML table that is rendered for the menu item of the menu control. The table and its many style attributes make this code less than optimal.

Figure 4 Default Menu HTML Output

<table id="ctl00_menuTop" class="ctl00_menuTop_2" 
       cellpadding="0" cellspacing="0" border="0">
  <tr onmouseover="Menu_HoverStatic(this)" 
      onmouseout="Menu_Unhover(this)" 
      onkeyup="Menu_Key(this)" id="ctl00_menuTopn0">
    <td>
      <table cellpadding="0" cellspacing="0" border="0" width="100%">
        <tr>
          <td style="white-space:nowrap;width:100%;">
            <a class="ctl00_menuTop_1"
               href="https://Msdn.WebStandards/Default.aspx">Main Page</a>
          </td>
          <td style="width:0;">
            <img src="/Msdn.WebStandards/WebResource.axd?d=hnH9bjBrxucw46WA5Xha0Kh9gZ-YF67wSyd4b51QsEc1&amp;t=632962190992968750" 
                 alt="Expand Main Page" 
                 style="border-style:none;vertical-align:middle;" />
          </td>
        </tr>
      </table>
    </td>
  </tr>
</table>

Because the HTML is rendered as a table when the data in the table is generally not tabular, this code is not considered to be Web standards compliant. Using an HTML table to render a list of menu items is like using a DataSet to tackle a job for which you'd typically use an array or collection of strings. The accepted way to render hierarchical data like this is to use the HTML unordered list, which makes sense when you think about it-a menu really is a series of nested lists.

Fortunately, Microsoft distributes the ASP.NET 2.0 CSS Friendly Control Adapters 1.0 toolkit, which lets you override the default output of controls to remove, replace, or inject HTML when the control is rendered. After several beta iterations, the toolkit was released and can be downloaded from asp.net/CSSAdapters/Default.aspx.

The CSS Control Adapters provide the ability to override the output of any control, whether delivered with ASP.NET 2.0, third-party, or custom, without modifying the source code of the control. As a developer, you do not have the source code for all the controls you use and even if you did, modifying it is not always the best way to override functionality. This is especially true if all you need to do is modify the rendered HTML.

The architecture that drives the control adapters is built on the Adapter or Wrapper design pattern. The abstract class ControlAdapter defines the base functionality for all adapters. The WebControlAdapter class inherits the ControlAdapter functionality while adding methods for rendering individual HTML tags. Classes like the Menu Adapter inherit from the WebControlAdapter to provide functionality specific to a control. Figure 5 shows the class diagram for the control adapters.

Figure 5 ASP.NET 2.0 Control Adapter Classes

Figure 5** ASP.NET 2.0 Control Adapter Classes **(Click the image for a larger view)

The implementation of this architecture is straightforward, especially for controls that already have adapters developed for them. Fortunately, most all the ASP.NET controls do have adapters. In the example shown, the MenuAdapter class is used to override the default HTML table layout with an unordered list.

The first step to accomplish this is to create or customize a browser definition file, which is used to detect the browser that is accessing the ASP.NET 2.0 site and provide specific functionality for that browser. This is a good way to provide a customized experience to users coming to the site from mobile devices. For use with CSS Control Adapters, however, the browser definition file is used to signify that compliant browsers should use one or more adapters.

The XML shown in Figure 6 shows a full browser definition file that tells ASP.NET to route all of the MenuControl classes to the MenuAdapter for all browsers that match the described criteria. The criteria describe all W3C-compliant browsers that support JavaScript and CSS. This would match most of the browsers used today. The browser definition file also gives you information you can use for all kinds of other customization of the user experience.

Figure 6 ASP.NET 2.0 Browser Definition File

<browsers>
  <browser refID="Default">
    <controlAdapters>
      <adapter controlType="System.Web.UI.WebControls.Menu"
               adapterType="CSSFriendly.MenuAdapter" />
    </controlAdapters>
  </browser>

  <browser id="W3C_Validator" parentID="default">
    <identification>
      <userAgent match="^W3C_Validator" />
    </identification>
    <capabilities>
      <capability name="browser"              value="W3C Validator" />
      <capability name="ecmaScriptVersion"    value="1.2" />
      <capability name="javascript"           value="true" />
      <capability name="supportsCss"          value="true" />
      <capability name="supportsCallback"     value="true" />
      <capability name="tables"               value="true" />
      <capability name="tagWriter"            
        value="System.Web.UI.HtmlTextWriter" />
      <capability name="w3cdomversion"        value="1.0" />
    </capabilities>
  </browser>
</browsers>

The last step in implementing the CSS Control Adapter is to create a class that is derived from the adapter class. Figure 7 shows the example menu adapter that ships with the ASP.NET 2.0 Control Adapter. The class derives from the MenuAdapter class, enumerates through all of the items that make up the controls, and overrides the HTML with the appropriate tags. Shown there is the portion of the class that renders the beginning of the unordered list in the BuildItems method.

Figure 7 Menu Control Adapter HTML Output

Public Class MenuAdapter
        Inherits System.Web.UI.WebControls.Adapters.MenuAdapter
    ...
        
    Protected Overrides Sub RenderContents(ByVal writer As HtmlTextWriter)
        If (Extender.AdapterEnabled) Then
            writer.Indent = writer.Indent + 1

            BuildItems(Control.Items, True, writer)

            writer.Indent = writer.Indent—1
            writer.WriteLine()
        Else
            MyBase.RenderContents(writer)
        End If
    End Sub

    Private Sub BuildItems(ByVal items As MenuItemCollection, _
            ByVal isRoot As Boolean, ByVal writer As HtmlTextWriter)
        If (items.Count > 0) Then
            writer.WriteLine()

            writer.WriteBeginTag("ul")
            If isRoot Then
                writer.WriteAttribute("class", "AspNet-Menu")
            End If
            writer.Write(HtmlTextWriter.TagRightChar)
            writer.Indent = writer.Indent + 1

            For Each item As MenuItem In items
                BuildItem(item, writer)
            Next

            writer.Indent = writer.Indent—1
            writer.WriteLine()
            writer.WriteEndTag("ul")
        End If
    End Sub
End Class

If you look at the HTML source in Figure 8, you can see that the table from the menu control is replaced with an unordered list. The unordered list is not the only noteworthy topic in the HTML output, however. The output is also noticeably cleaner because it is not cluttered with style and scripting code. All of the positioning and style now resides in the CSS file for the menu and the menu is now considered Web standards-compliant.

Figure 8 Menu Control Adapter HTML Output

<div class="AspNet-Menu-Horizontal">
  <ul class="AspNet-Menu">
    <li class="AspNet-Menu-WithChildren">
    <a href="https://Default.aspx" class="AspNet-Menu-Link">Web Standards</a>
      <ul>
        <li class="AspNet-Menu-Leaf">
          <a href="https://ControlAdapters.aspx">Control Adapters Sample</a>
        </li>
        <li class="AspNet-Menu-Leaf">
          <a href="https://AccessibleForm.aspx">Accessible Form</a>
                    </li>
                </ul>
            </li>
        </ul>
</div>

The CSS Control Adapter comes with adapters for many controls, including for the Tree view, Login, and CreateUserWizard, which represent the controls that notoriously render tables when they should not. It takes only a few minutes to integrate the samples into an existing project and customize to your liking.

Master Pages and Themes

Now that you have the tools to render controls that comply with Web standards, you can make an entire site compliant. The combination of Master Pages and Themes provide a powerful and flexible infrastructure for a Web site.

Master Pages allow Web developers to create flexible templates for Web pages. A powerful tool for creating reusable components across Web pages, Master Pages also provide a way to ensure standards compliance throughout a site. Creating a Master Page that uses the XHTML 1.1 DocType is good way to ensure compliance across all pages within the site. Master Pages are also handy for letting you make all changes to the DocType in one place when, for example, a site migrates from XHTML 1.0 Transitional to Strict.

ASP.NET 2.0 Themes allow you to create multiple designs for the same content, enhancing accessibility. For example, themes can improve accessibility for visually impaired users by letting them increase the font and image size. Placing the ability to switch themes within the Master Page allows users to view the site in a manner that best meets their individual needs.

One technique I find valuable to enable users to switch themes is to define a class that is derived from the Page class. The ability to switch themes is only available very early in the lifecycle of an ASP.NET page-in the OnPreInit method. The class in Figure 9 shows how to capture the theme a user has selected and apply it in the overridden method.

Figure 9 ThemeSelectablePage Class

''' <summary>
'''  Override Page with PreInit method to allow for theme switching
''' </summary>
''' <remarks>"__Theme" represents the RadioButton list of theme</remarks>
Public Class ThemeSelectablePage
        Inherits System.Web.UI.Page
    Protected Overloads Overrides Sub OnPreInit(ByVal e As EventArgs)
        For Each key As String In Me.Request.Form.AllKeys
            If key.IndexOf("__Theme") > -1 Then
                Page.Theme = Me.Request.Form(key).Trim
                Exit For
            End If
        Next
        MyBase.OnPreInit(e)
    End Sub
End Class

This class is looking for a request form variable with a predefined name and passing the value to the theme class. All Web pages that implement this class will provide the infrastructure needed to enable multiple themes. This is a very simple way to add theme switching to all pages on a site.

The Petition

This article discussed why Web standards are so important and looked at some techniques that can be used to create compliant Web sites. It can be challenging to adopt these standards because it is often not the easiest path to take, but it is the best way to ensure that the controls and HTML you build today will be accessible to a broader base of users on a larger number of devices in the future. Browsers are increasingly conforming to these standards and will continue to do so; the burden now falls on the development community to produce Web standards-compliant code.

Ben Waldron is a founding partner at Pollinate Media, an Interactive Branding and Innovation Company located in Portland, Oregon. Ben can be contacted for questions or opportunities via e-mail: ben.waldron@pollinatemedia.com.