# Using a style switcher to provide a conforming alternate version

ID: C29

Technology: css

Type: Technique

## When to Use

CSS used with client-side or server-side scripting.

## Description

When some aspect of the default presentation of a Web page does not meet a Success Criterion, it is possible to meet that requirement using the "Alternate Version" clause in the conformance requirements (Conformance Requirement 1). For some requirements, invoking a style switcher via a link or control on the page that can adjust the presentation so that all aspects of the page conform at the level claimed allows authors to avoid having to provide multiple versions of the same information.

The objective of this technique is to demonstrate how CSS can be used in combination with scripting to provide conforming alternate versions of a Web page. In this technique, an author provides alternative views of the content by providing controls that adjust the CSS that is used to control the visual presentation of content. Controls provided within the Web page allow users to select or modify the presentation in a way that meets the success criterion at the level claimed. This makes it possible for different visual presentations to be selected by users in situations such as the following:

- the user may not be able to adjust browser or operating system settings, due to a lack of familiarity or rights
- the text is provided in a manner that does not respond to browser or operating system settings (such as text within an image)
- the default presentation of the content does not include sufficient contrast for some users

For this technique to be used successfully, three things must be true.

1. The link or control on the original page must itself meet the success criterion to be met via the alternate presentation. For example, if a style switcher is used to provide increased font sizes and the control is presented using a small font, users may not be able to activate the control and view the alternate presentation.
2. The new page must contain all the same information and functionality as the original page.
3. The new page must conform to all of the Success Criteria for the desired level of conformance. For example, an alternate stylesheet can not be used to meet one requirement if it causes a different requirement to no longer conform.

When using a style switcher, it is important to consider the following challenges and limitations:

- The number and type of changes that a user can make is limited to the scope of the controls provided by the author of the Web page. A variety of presentation and preferences should be provided in order to address the needs of as wide an audience as possible. However, it is also important for authors to consider interactions between preferences and the complexity for users that might result from providing large numbers of options to users.
- Maintaining the user's preference from one page to the next may be achieved by storing a cookie on the user's machine (see Resources section for more information) or by including their preferences in a profile saved on the Web server by passing a query string parameter, or by other means.
- The technical method used to implement a style switcher may be subject to the support and availability of one or more technologies on the user's machine (for example, many client-side solutions require support for both JavaScript and CSS). Unless these technologies are relied upon for conformance, authors should consider using server-side technologies where client-side support and availability of technologies can not be assured. Alternatively, the use of techniques which ensure that content will transform gracefully when one or more of the technologies used are not available can be an effective way to enhance pages when support for these technologies is not relied upon for conformance.

## Examples

### Using a JavaScript control to apply a different external CSS file

This example is of a page that provides links to change text and background colors for the page via JavaScript. The links should only be inserted if JavaScript is supported by and available on the user's system. Otherwise, selecting the links will not result in the desired changes. This can be achieved by using script to insert the links themselves (which means that the links would only be present when scripting is supported and available).

The following code shows the JavaScript-dependent color-change links and a snippet of other content in the Web page, the associated style sheet rules, and the JavaScript that changes the style sheet in use when a color-change link is selected.

The example applies only to the current page view. In a production environment, it would be advisable to save this preference in a cookie or server-side user profile, so that users would only have to make the selection once per site.

#### The HTML components

    <!doctype html>
    <html lang="en">
      <head>
        <meta charset="utf-8">
        <link href="main.css" rel="stylesheet">
        <link id="currentCSS" href="defaultColors.css" rel="stylesheet">
      </head>
      <body>
        <div id="colorswitch">
        <p>Change colors:</p>
        <ul class="inline">
          <li>
            <a href="#" onClick="javascript:changeColors('altColors1.css');return false;"
    	id="altColors1">dark blue on white</a>
          </li>
          <li>
            <a href="#" onClick="javascript:changeColors('altColors2.css');return false;"
    	id="altColors2">yellow on black</a>
          </li>
          <li>
            <a href="#" onClick="javascript:changeColors('altColors3.css');return false;"
    	id="altColors3">black on pale yellow</a>
          </li>
          <li>
            <a href="#" onClick="javascript:changeColors('altColors4.css');return false;"
    	id="altColors4">black on white</a>
          </li>
          <li>
            <a href="#" onClick="javascript:changeColors('defaultColors.css');return false;"
    	id="default">Reset to default</a>
          </li>
        </ul>
      </div>
      <div id="mainbody">
        <h1>Conference report</h1>
          <p>Last week's conference presented an impressive line-up of speakers...</p>
        </div>
      </body>
    </html>

#### The CSS components

##### In main.css

    body{ font-family: Geneva, Arial, Helvetica, sans-serif; margin: 2em; }

    #mainbody {
      padding: 1em;
    }

    #colorswitch {
      float: right;
      width: 12em;
      border: 1px #000066 solid;
      padding:0 1em 1em 1em; margin:0;
    }

    #colorswitch p {
      padding-top:.5em;
      font-weight:bold;
    }

##### In defaultColors.css

    body, p {
      color:#000000;
      background-color:#FFFFFF;
    }

    h1, h2, h3 {
      color:#990000;
      background-color:#FFFFFF;
    }

##### In altColors1.css

    body, h1, h2, h3, p, a {
      color:#000066;
      background-color:#FFFFFF;
    }

##### In altColors2.css

    body, h1, h2, h3, p, a {
      color:#FFFF33;
      background-color:#000000;
    }

##### In altColors3.css

    body, h1, h2, h3, p, a {
      color:#000000;
      background-color:#FFFF99;
    }

##### In altColors4.css

    body, h1, h2, h3, p, a {
      color:#000000;
      background-color:#FFFFFF;
    }

#### The JavaScript components

    function changeColors (newCSS){
      document.getElementById('currentCSS').href = newCSS;
    }

A working example of this code, Using a JavaScript control to apply a different external CSS file, is available.

### Using a client-side JavaScript to change a CSS property

This example can be used for simple changes to a section of content and may be less practical for complex sites or pages. The example uses a client-side JavaScript to change the class name to visually present the user's color selection (from a defined set of options) as a background for highlighting specific content.

The following code includes JavaScript calls within the HTML code to aid understanding of the technique. However, the author is encouraged to use current best practice for including JavaScript (see resources for more information about Unobtrusive JavaScript and progressive enhancement).

#### The HTML components

    <h1>Product comparison</h1>
    <p>The products you selected to compare are listed below.
      Any differences between the products are highlighted and italicized.</p>
    <p class="inlinePara">Change hightlight color: </p>
    <ul class="inline">
      <li>
        <a href="#" onClick="changeColor('hghltLightYellow');return false;"
         class="hghltLightYellow">light yellow</a>
      </li>
      <li>
        <a href="#" onClick="changeColor('hghltBrightYellow');return false;"
         class="hghltBrightYellow">bright yellow</a>
      </li>
      <li>
        <a href="#" onClick="changeColor('hghltLightBlue');return false;"
         class="hghltLightBlue">light blue</a></li>
    	<li>
        <a href="#" onClick="changeColor('hghltBrightBlue');return false;"
         class="hghltBrightBlue">bright blue</a>
      </li>
      <li>
        <a href="#" onClick="changeColor('hghltLightRed');return false;"
         class="hghltLightRed">light red</a>
      </li>
      <li>
        <a href="#" onClick="changeColor('hghltDrkRed');return false;"
         class="hghltDrkRed">dark red</a>
      </li>
    </ul>
    <table>
      <tr>
        <td> </td>
        <th scope="col">Product 1</th>
        <th scope="col">Product 2</th>
      </tr>
      <tr>
        <th scope="row">Aspect 1</th>
        <td>Yes</td>
        <td>Yes</td>
      </tr>
      <tr>
        <th scope="row">Aspect 2</th>
        <td class="hghltLightYellow">Yes</td>
        <td class="hghltLightYellow">No</td>
      </tr>
      <tr>
        <th scope="row">Aspect 3</th>
        <td>Yes</td>
        <td>Yes</td>
      </tr>
    </table>

#### The CSS components

    body { color:#000000; background-color:#FFFFFF; }
    .hghltLightYellow { color: #000000; background-color: #FFFF99; font-style:oblique; }
    .hghltBrightYellow { color: #000000; background-color: #FFFF00; font-style:oblique; }
    .hghltLightBlue { color: #000000; background-color: #33FFFF; font-style:oblique; }
    .hghltBrightBlue { color: #FFFFFF; background-color: #0000FF; font-style:oblique; }
    .hghltLightRed { color: #000000; background-color: #FF6266; font-style:oblique; }
    .hghltDrkRed { color: #FFFFFF; background-color: #993300; font-style:oblique; }

    .inlinePara { display:inline; }
    .inline { display: inline; margin-left:0px; padding-left:0px; line-height:3em; }
    .inline li { display:inline; }
    .inline li a { padding: 0.5em 1em; border: 2px solid #000000; }

#### The JavaScript components

    function changeColor(hghltColor) {
      // collects table data cells into an array
      var els = document.getElementsByTagName('td');

      // for each item in the array, look for a class name starting with "hghlt"
      // if found, change the class value to the current selection
      // note that this script assumes the  'td' class attribute is only used for highlighting

      for (var i=0; i<els.length; i++) {
        if (els[i].className.indexOf("hghlt") == 0) { els[i].className = hghltColor; }
      }
    }

A working example of this code, Using a client-side JavaScript to change a CSS property, is available.

### Using PHP $_GET to apply a different external CSS file

This simple example uses PHP $_GET to assign one of two available external style sheets. Similar functionality could be achieved using a variety of PHP features. The example applies only to the current page view. In a production environment, it would be advisable to save this preference in a cookie or server-side user profile, so that users would only have to make the selection once per site.

The following code is PHP, but a similar approach would work with a variety of server-side technologies.

#### The PHP and HTML components

##### At the beginning of the PHP page

    <?php
      $thestyle = $_GET['set'];
      if ($thestyle == "style1") {
        $thestyle = "style2";
      }
      else {
        $thestyle = "style1";
      }
    ?>

##### In the <head> section

    <link rel="stylesheet" media="screen" href="<?php echo($thestyle);?>.css">

##### In <body> section

    <?php
      if ($thestyle == "style1") {
        echo "<a href=\"index.php?set=style1\">Switch to Style Sheet Two</a>";
      }
      else {
        echo "<a href=\"index.php?set=style2\">Switch to Style Sheet One</a>";
      }
    ?>

    <div id="mainbody">
      <h1>Conference report</h1>
      <p>Last week's conference presented an impressive line-up of speakers...</p>
    </div>

#### The CSS components

##### In style1.css

    body, p { color:#000000; background-color:#FFFFFF; }
    h1, h2, h3 {color:#990000; background-color:#FFFFFF; }

##### In style2.css

    body, h1, h2, h3, p, a { color:#FFFF00; background-color:#000000; }

A working example of this code, Using PHP $_GET to apply a different external CSS file, is available.

## Tests

### Procedure

1. Check that the Web page contains controls that allow users to select alternate presentations.
2. Check that the control changes the presentation by modifying individual CSS style properties or by activating an alternate style sheet.
3. Verify that the resulting page is a conforming alternate version for the original page.

### Expected Results

- All of the above checks are true.

## Related Techniques

- G140
- G174
- G178
- G188
- G189
- G191
- G206
- C7
- C22
- SCR38

## Resources

- Build your own PHP style sheet switcher

### Using cookies

A user's selection can be made persistent across pages, and from one visit to another, by storing information on the user's computer via a cookie. This functionality requires cookies to be supported by and allowed on the user's computer. Cookies can be created, read, modified and erased by using client-side scripts, such as Javascript, or by server-side scripts, such as CGI scripts. Reliance on client-side technologies will require the support and availability of the technology on the user's computer in addition to supporting and allowing cookies.

Information on creating and using cookies can be found on the web. Here are some suggestions:

- JavaScript - Cookies
- Write Your First HTTP Cookie
- ASP Cookies
- Programming Ruby

It is recommended that authors test for cookie support and provide an extra control if cookies are not supported. This extra control should include information about the persistence of the selection, such as "Apply selection to all pages". The message or page presented to the user in response to selecting the extra control provides information about the cookie requirement and their options for solving it. In the event that the user is unable to turn cookie support on, include a statement about what this will mean for them if they choose to continue to browse the site and provide information about how they can adjust their user agent to achieve similar results.

For example, "Your browser is not configured to accept cookies. On this site, cookies are required in order to apply your selected changes across all of the pages of the site. To find out how to enable cookies on your computer, visit turn cookies on or off. Note that this may require administrative rights for the computer you are using. Without cookie support, your settings will not persist to include other pages on this site. We are endeavoring to provide this functionality without relying on your computer's capability. In the meantime, you will be able to select the change for each page that you visit."

### Progressive Enhancement and Unobtrusive Javascript

Current best practice for implementing JavaScript in an HTML page is to use it in a way that separates the behavior of content from its structure and presentation. The terms 'Progressive Enhancement' and 'Unobtrusive JavaScript' are often used to describe scripts that enhance or improve the functionality of a page, yet transform gracefully so that content continues to function even when JavaScript is not supported.

Here are some suggested starting points for more information:

- Behavioral Separation
- Wikipedia: Unobtrusive JavaScript
- Progressive enhancement