Build User-Controlled Style Sheets for Greater Accessibility

Much of the discussion surrounding Web accessibility concerns users who are legally blind and require a text reader such as JAWS. But organizations such as the American Foundation for the Blind also support sighted people who have a serious visual impairment. Visitors with impaired sight can read Web pages, but may need a high-contrast, large font typeface to do so.

While there are 1.8 million Americans who are legally blind, another 7.7 million have a serious visual impairment that affects their reading ability. With an aging population, this number is expected to double by the year 2030.

In this article, we’ll see how to let visitors generate a large print version of your pages by changing the styles applied to your pages. The approach we use is easy, and doesn’t require sweeping changes to your underlying HTML code. You can improve the accessibility of your site without a great deal of effort.

Along the way we’ll also learn three different methods to change your styles: by changing specific element IDs, by changing CSS selectors, and by swapping entire style sheets. Hopefully these three methods will boost your knowledge of style sheets and have application beyond this article.

The Model

The AFB Website offers a good example what we want to achieve. This page allows visitors to set the typeface used in the site, setting font size, color, and background contrast. The visitor’s preferences are then stored in a cookie and applied to all other pages in the site and on all future visits.

Why go to this trouble when users can increase their browser’s default font size by themselves using the View – Text Size menu? The text size options offered by Internet Explorer and other browsers are limited, allowing users to increase font size by only 125%. To support visitors with a serious visual impairment, we need larger font and the ability to increase contrast.

The AFB site uses Active Server Pages, and therefore changes page styles through server-side code. Our method will use JavaScript and Dynamic HTML to do the same thing.

The AFB site also offers users several font size and color options. To keep things simple, we’ll offer a single alternative in this article. However, you can easily extend the methods described here to offer several options to your visitors.

Our Test Page

First, let’s create a simple page whose style we’d like to change:

<div id="test"> 
<h2>Headline</h2>
<p>This is the content section of our document.</p>
</div>

<p><a href="javascript:;" onClick="changeStyles();">Change styles</a>

This simple page defines a headline and a paragraph of text, and wraps a DIV element around them to make the page content easier to manipulate with JavaScript.

It also defines a "Change styles" link that executes a JavaScript function to change styles. There are three ways we can write the changeStyles( ) function:

  1. Changing styles for specific page elements by their ID
  2. Changing the style of all elements by their CSS selector
  3. Changing the style sheet assigned to our page

Each of these methods has its own strengths and weaknesses.

Changing Elements by ID

Changing the style of an individual page element is a straightforward process. We first access the JavaScript object corresponding to the element, and then change the value of individual properties.

Our test page wraps a DIV element around the page content, so we can use the ID of this element to find the appropriate object:

      1: <script language="javascript"> 
     2: ns4 = document.layers;
     3: ie = document.all;
     4: ns6 = document.getElementById && !document.all;
     5:
     6: function changeStyles (id) {
     7:    if (ns4) {
     8:       alert ("Sorry, but NS4 does not allow font changes.");
     9:       return false;
    10:    }
    11:    else if (ie) {
    12:       obj = document.all[id];
    13:    }
    14:    else if (ns6) {
    15:       obj = document.getElementById(id);
    16:    }
    17:    if (!obj) {
    18:       alert("unrecognized ID");
    19:       return false;
    20:    }
    21:
    22:    obj.style.color = "yellow";
    23:    obj.style.backgroundColor = "black";
    24:    obj.style.fontSize = "300%";
    25:
    26:    return true;
    27: }
    28:
    29: </script>

Lines 2-4 determine which version of the DOM is being used, and set up a series of variables to store this information. Lines 7-20 load the JavaScript object into a variable called obj using the method appropriate for the browser.

Notice that lines 7-10 simply post an alert. This is necessary because Netscape Versions 4 and earlier do not allow us to change font styles after the page has loaded.

Lines 22-24 are the heart of our script, changing the text color to yellow, the background color to black, and increase font size by 300%.

Finally, notice that this implementation of the changeStyles( ) function takes id as an input argument, indicating the ID of the element whose style is to be changed. This requires us to change the way we call the function, as shown below.

<p><a href="javascript:;" onClick="changeStyles('test');">Change   
styles</a>

The advantage of this approach is that it's fairly straightforward. If you are familiar with Dynamic HTML, the method is easy to follow.

But this approach is also brittle. In practice, it's a little awkward to wrap a DIV element around your entire page content. More seriously, use of the DIV element poses inheritance problems under Internet Explorer, where the H2 tag containing the page headline doesn't inherit the font size assigned to the DIV.

As a result, this method is best used on a limited scale, when we only want to change the style of selected areas of our page.

Changing Elements by Selector

A more flexible method for giving users control over text presentation is to let them change styles at the selector level. A CSS selector is the left-hand portion of a style rule -- the part that defines the HTML elements to which the rule applies. For example, the P tag is the selector in the CSS rule shown below.

P   { font-size: 12pt; font-family: Arial }

If we change the style associated with any given selector, this will change large portions of our document with minimum of effort.

The code below shows a rewrite of our script to do this.

      1: <script>  
     2: ns4 = document.layers;  
     3: ie  = document.all;  
     4: ns6 = document.getElementById && !document.all;  
     5:  
     6: function changeStyle (selector) {  
     7:    if (ns4) {  
     8:       alert ("Sorry, but NS4 does not allow font changes.");  
     9:       return false;  
    10:    }  
    11:    else if (ie) {  
    12:       setNewStyle('P');  
    13:       setNewStyle('H2');  
    14:    }  
    15:    else if (ns6) {  
    16:       alert('Sorry, Netscape does not support this function.');  
    17:    }  
    18:  
    19:    return true;  
    20: }  
    21:  
    22: function setNewStyle(selector) {  
    23:    style = getStyleObj(selector);  
    24:    if (!style) return false;  
    25:  
    26:    style.color = "yellow";  
    27:    style.backgroundColor = "black";  
    28:    style.fontSize = "300%";  
    29: }  
    30:  
    31: function getStyleObj (selector) {  
    32:    for (x=0; x < document.styleSheets.length; x++) {  
    33:       var oStyleSheet = document.styleSheets[x];  
    34:       if (ie4) {  
    35:          for (y=0; y < oStyleSheet.rules.length; y++) {  
    36:             var oRule = oStyleSheet.rules[y];  
    37:             if (oRule.selectorText == selector) {  
    38:                return oRule.style;  
    39:            }  
    40:         }  
    41:       }  
    42:    }  
    43:    return false;  
    44: }  
    45:  
    46: </script>

The changeStyle( ) function again branches based on the browser being used. Lines 12-13 apply to Internet Explorer and involve two separate calls to a setNewStyle( ) function: one call to change all P elements and another to change all H2 elements.

The setNewStyle( ) function is defined in lines 22-29. It begins by calling another function called getStyleObj( ) to fetch the JavaScript object corresponding to the selector input argument, and then sets the font size, color, and background color of the element.

So far this version of our script isn't much different from our earlier ID-based approach. However, the heart of our script is the function getStyleObj( ) defined on lines 31-44. This code searches all style sheets associated with the document, checks style rule defined in each of these sheets, and tests if the rule's selectorText property matches the selector input argument passed to the function. The function returns the style object for the first rule matching our selector criteria.

Note that getStyleObject( ) will work only if a style rule has been defined for a given selector. If no rule exists, then getStyleObj( ) will return false. So in order for this code to work properly for our test page, we need to add a STYLE element defining rules for P and H2 elements, as shown below.

<style>  
P { font-size : 10pt; }  
H2 { font-size : 10pt; }  
</style>

By this point you may also have noticed the significant limitation of this method: it only works for Internet Explorer. A bug in the Gecko rendering engine, which is used by Netscape Versions 6-7 browsers, keeps the selectorText property from working properly. This was corrected in recent versions of Gecko, but not soon enough to support Netscape 7.

So, while this approach provides a lot of flexibility, it is perhaps best used on an Intranet where Internet Explorer is the standard browser.

Changing Style Sheets

The final method for customizing text presentation is to allow users to switch to an alternate style sheet. Instead of changing styles for individual page elements or changing specific selectors, this replaces the entire style sheet.

While this method isn't as flexible as changing individual selectors, it is easy to set up, and is supported by all browsers except Netscape Version 4.

To apply this method, first create two external style sheets: a default style sheet and a large print style sheet.

First, place the code below in a file named default.css. This is the code for our default style sheet.

P { font-size : 10pt; }   
H2 { font-size : 10pt; }

Next, place the code below in a file named accessible.css. This will be our large print style sheet.

P,H2 { font-size : 200%; color : yellow; background-color : black; }

We then tie these style sheets to our document by placing this code inside the HEAD section of our page:

<link rel="stylesheet" type="text/css"    
href="default.css" id="default">  
<link rel="stylesheet" type="text/css"    
href="accessible.css" id="accessible">

When we define two or more external style sheets for our document, we create a potential CSS conflict for the browser, and different browsers will resolve this conflict in different ways. Internet Explorer will resolve these conflicts in favor of the first style sheet listed. Gecko-based browsers, such as Netscape and Mozilla, will favor the last style sheet listed. Netscape will also allow users to chose between alternate style sheets through its View - Use Style menu.

Since we want our page to display consistently across browsers, we need to deactivate the accessible.css style sheet so there is only one active style sheet when the page loads. To do this, we add the following script code to the HEAD section of our page.

<script>   
ns4 = document.layers;  
 
if (!ns4) {  
  accessibleSheet = document.getElementById('accessible');  
  accessibleSheet.disabled = true;  
}  
</script>

This determines if Netscape Version 4 is being used (in which case we do nothing) and deactivates the accessible.css style sheet if not.

Our next step is to write the changeStyles( ) function so that it enables accessible.css and disables default.css. The code for the new function is shown below.

function changeStyles() {   
  if (ns4) {  
alert ("Sorry, but NS4 does not allow us to change styles.");  
     return false;  
  }  
  else {  
     defaultSheet = document.getElementById('default');  
     defaultSheet.disabled = true;  
 
     newSheet = document.getElementById('accessible');  
     newSheet.disabled = false;  
  }  
 
  return true;  
}
Making It Stick

Regardless of the method you use to change styles, you'll want your changes to be persistent. Unless we do this, the user will have to choose large fonts on every page in the site.

We can make our changes persistent by setting a cookie to indicate the user's style preference. Cookie code is complex, so for this article we'll use a ready-made cookie library available from WebMonkey.

The code below shows how to integrate the cookie code with our style sheet swapping script. Changes to support cookies are shown in bold.

      1: <html>   
     2: <head>  
     3: <link rel="stylesheet" type="text/css"    
href="default.css" id="default">  
     4: <link rel="stylesheet" type="text/css"    
href="accessible.css" id="accessible">  
     5: <script language="javascript" src="monkeylib.js"></script>  
     6:  
     7: <script>  
     8: ns4 = document.layers;  
     9:  
    10: if (!ns4) {  
    11:    if (WM_readCookie('siteStyle') == 'accessible') {  
    12:       changeStyles();  
    13:    }  
    14:    else {  
    15:       accessibleSheet = document.getElementById('accessible');  
    16:       accessibleSheet.disabled = true;  
    17:    }  
    18: }  
    19: </script>  
    20:  
    21: </head>  
    22: <body>  
    23: <script>  
    24:  
    25: function changeStyles () {  
    26:    if (ns4) {  
    27:       alert ("Sorry, NS4 does not let us    
to change styles.");  
    28:       return false;  
    29:    }  
    30:    else {  
    31:       defaultSheet = document.getElementById('default');  
    32:       defaultSheet.disabled = true;  
    33:  
    34:       newSheet = document.getElementById('accessible');  
    35:       newSheet.disabled = false;  
    36:  
    37:       WM_setCookie('siteStyle','accessible',17520);  
    38:    }  
    39:  
    40:    return true;  
    41: }  
    42:  
    43: </script>  
    44:  
    45: <h2>Headline</h2>  
    46: <p>This is the content section of our document.</p>  
    47:  
    48: <a href="javascript:;" onClick="changeStyles()">Set large    
    49: fonts</a>

Line 37 sets a persistent cookie named siteStyle to store the value "accessible." Line 11-17 check for the existence of this cookie, and call the changeStyles( ) function if it has been set to "accessible".

Applying It


Regardless of the method you use to give users control over page style, keep in mind that normal CSS precedence rules still apply. If you define inline styles for elements of your page, these will override the user-selected styles and undermine accessibility.

Having said that, none of these methods require significant changes to your underlying HTML code. In fact, much of this code is cut-and-paste friendly, making it easy to improve the accessibility of your pages. It's a great thing when you can do something to make your site more accessible without hours of effort.

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

No Reader comments

Comments on this post are closed.