Techniques for High-Contrast-Friendly Icons

This post was originally published on the Yahoo! Accessibility Blog.

CSS background images are the most popular means of using image sprites, but this technique can cause problems for users of High Contrast mode in Windows. Background images are disabled when High Contrast mode is enabled, causing all sprites to disappear. For example, consider the following toolbar containing buttons labeled with icons created using background images:

Screen shot of a toolbar with buttons labeled with icons created using background images

Here is how the toolbar renders when High Contrast mode is enabled.

Screen shot of a toolbar with buttons labeled with icons created using background images rendered in High Contrast mode

As illustrated, use of CSS background images can result in information loss for users when High Contrast mode is enabled, especially in the following use cases:

  • An image is the only visual label for a UI control (e.g. a button, menuitem, etc.)
  • An image conveys state (e.g. selected, checked, etc.) or other supplemental information (e.g. a message has an attachment)

This is especially problematic considering High Contrast mode is designed to make the UI easier to see. Fortunately there are several alternatives to background images that work in High Contrast mode.

Understanding High Contrast Mode

First, what is High Contrast mode, and more importantly, who benefits?

In High Contrast mode Windows will change the foreground colors (used for text, borders, etc.) and background colors to create a greater contrast. The font size is often increased as well. These adjustments make it easier for users with visual impairments to see the screen.

Some examples of the types of users who benefit from High Contrast mode are:

  • Users who have low vision; anyone with a visual impairment that can't be corrected with glasses, but is not in the range of legal blindness. Users with low vision may use screen magnification, bigger screens, larger fonts, high contrast, screen reading, or other assistive technology. Users with low vision can perceive light, so more contrast can make it easier to see the screen.
  • Users with color vision deficiencies (also known as color blindness)
  • Users who's eyes are sensitive to light. Users can turn on low contrast theme or darker themes as their eyes are very sensitive to light.

Solutions

There are several alternatives to using background images, each with benefits and drawbacks. As with all accessibility solutions, there's no silver bullet. Consider each solution relative to the constraints or demands of the web site or application and choose the solution that works best.

Use the content property

Steve Faulkner, Nicolas Gallagher, Thierry Koblentz, have all authored articles on using the content property to create icons that work in High Contrast mode.

Here's how it works. Consider the following HTML for a toolbar:


<div role="toolbar">

<button type="button">Print</button>

<button type="button">Find</button>

<button type="button">Save</button>

<button type="button">Settings</button>

<button type="button">Info</button>

</div>

To add an icon to each button:

  1. Give the button a fixed height and width, and set the overflow property to "hidden".

    .toolbar button {

    border: 1px solid #333;

    background: #bbb;

    padding: 0;

    margin: 0 3px 0 0;

    width: 36px;

    height: 36px;

    overflow: hidden;

    }

  2. Use the :before pseudo element and the content property to add the image to the button.

    .toolbar button:before {

    display: inline-block;

    content: url('http://findicons.com/files/icons/2340/preview/toolbar_icon_set_full.png');

    }

  3. Use negative margins to move the image into position.
    .toolbar .prnt:before {

    margin: -73px 0 0 -37px;

    }

    .toolbar .find:before {

    margin: -145px 0 0 -181px;

    }

    .toolbar .save:before {

    margin: -73px 0 0 -145px;

    }

    .toolbar .sets:before {

    margin: -109px 0 0 -73px;

    }

    .toolbar .info:before {

    margin: -145px 0 0 -145px;

    }

This CSS will inject an image before the button's text node. With the overflow property set to "hidden," the text will be hidden from view while still being accessible to users of screen readers.

The technique has a number of advantages, the foremost being the changes are isolated to CSS. So switching to this technique from background images doesn't require a change to markup. Other advantages include:

The major disadvantage to this technique is the content property isn't supported in IE < 8. But there are several solutions for supporting older versions of IE, the first being to consider support for High Contrast mode a Progressive Enhancement: Use content for modern browsers, fall back to background images for older versions of IE.

Here's the CSS updated with support for IE 6 and 7.


.toolbar button:before {

display: inline-block;

content: url('http://findicons.com/files/icons/2340/preview/toolbar_icon_set_full.png');

}

.toolbar button {

*background: url('http://findicons.com/files/icons/2340/preview/toolbar_icon_set_full.png') no-repeat;

*text-indent: 36px;

}

.toolbar .prnt {

*background-position: -38px -74px;

}

.toolbar .prnt:before {

margin: -73px 0 0 -37px;

}

.toolbar .find {

*background-position: -182px -146px;

}

.toolbar .find:before {

margin: -145px 0 0 -181px;

}

.toolbar .save {

*background-position: -146px -74px;

}

.toolbar .save:before {

margin: -73px 0 0 -145px;

}

.toolbar .sets {

*background-position: -74px -110px;

}

.toolbar .sets:before {

margin: -109px 0 0 -73px;

}

.toolbar .info {

*background-position: -146px -146px;

}

.toolbar .info:before {

margin: -145px 0 0 -145px;

}

Use LESS or Sass to make the fork for IE more manageable. Here's an example of the previous CSS consolidated using LESS:

.positionIcon (@x, @y) {

&:before {

margin: @y 0 0 @x;

}

*background-position: @x - 1px @y - 1px;

}

.toolbar .prnt {

.positionIcon(-37px, -73px);

}

.toolbar .find {

.positionIcon(-181px, -145px);

}

.toolbar .save {

.positionIcon(-145px, -73px);

}

.toolbar .sets {

.positionIcon(-73px, -109px);

}

.toolbar .info {

.positionIcon(-145px, -145px);

}

Here's an example of how it all comes together: high-contrast-friendly icons using the content property and background images for IE 6 & 7.

Use <img src="https://media.zenfs.com/en-US/blogs/ydnblog/toolbar.png" width="150"> sprites

Rather than use the CSS content property to add an image, insert the <img width="150"> directly into the markup.

The CSS for positioning the image is virtually identical to the content property technique, the difference being the style rules address the <img width="150"> rather than the :before pseudo element.

Here's an example: high-contrast-friendly icons using the <img width="150"> element

Credit for this technique goes to Thierry Koblenz, and Artz Studio published a good article on the subject.

This technique works in all browsers, making it a good choice when support for High Contrast mode in older versions of IE is required. There are some disadvantages to this technique, mainly:

  • Harder to theme with the path to the image in the markup.
  • Because negative margins are used to position the image, the alternative text won't be displayed when images are disabled or fail to load but CSS is enabled.

Use content for modern browsers and CSS expressions for IE 6 & 7

The final solution would be to use a CSS expression to supplement the lack of support for the content property in IE 6 and 7.

The major advantage to this technique is the CSS expression provides the flexibility of the content property; the path to the image is centralized in the CSS, enabling the creation of themes. The disadvantage to this technique is CSS expressions have the potential to cause performance problems. To help mitigate slowness, this technique uses Steve Souder's recommended one-time expressions solution.

Here's an example of this technique: high-contrast-friendly icons using the content property and CSS expressions for IE 6 & 7.

This technique might be a good choice when support for High Contrast mode in older versions of IE is required and the given site or application doesn't have many instances of icons. But as with all things performance, measure the performance impact of the CSS expressions before putting them into production.

Testing High Contrast Mode

Regardless of the technique, it is important to test in High Contrast mode. For more on enabling High Contrast mode, see Microsoft's documentation:

Recommendation

Of the three, using the content property with background images for IE 6 and 7 seems like the preferred solution. It strikes the right balance between what is desirable for both the developer and the user. For developers it provides both an easy means of fixing icons for existing sites, while being a future-proof accessibility design pattern for the development of new sites. Although IE 6 + 7 users will be required to upgrade their browser for High Contrast mode support, it's a solution geared toward the future, rather than browsers with declining marketshare. So, while it might not be a silver bullet today, it's close. And it certainly will be once IE 6 and 7 are gone.

Ultimately, the choice is yours. Use the comparison table to help guide your decision, as it's designed to clearly call out the pros and cons of each technique.

RTL Support

Vertically arrange icons in the sprite for right-to-left (RTL) language support. This will ensure the icons are positioned correctly regardless of the orientation of the screen.

Muscle Memory

Often the biggest hurdle for implementing new techniques is changing habits. While CSS background images continue to be useful for images used for decoration (e.g. gradients), consider this new technique whenever CSS is used to replace text on screen with an image. That should help put it in muscle memory.