A new image replacement technique was recently added to the HTML5 Boilerplate project. This post explains how it works and how it compares to alternative image replacement techniques.

[15 December 2012] This technique is no longer used in HTML5 Boilerplate. It’s been replaced by another, more reliable approach.

Here’s the CSS behind the recent update to the image replacement helper class in HTML5 Boilerplate. It has also made its way into the Compass framework.

.ir {
font: 0/0 a;
text-shadow: none;
color: transparent;
}

What does each declaration do?

  • font:0/0 a – a shorthand property that zeros out the font size and line-height. The a value acts as a very short font-family (an idea taken from the BEM implementation of this method). The CSS validator complains that using 0/0 in the shorthand font property is not valid, but every browser accepts it and this appears to be an error in the validator. Using font:0px/0 a passes validation but it displayed as font:0/0 a in the code that the validator flags as valid.
  • text-shadow:none – makes sure that any inherited text shadow is removed for the text. This prevents the chance of any text shadow colors showing over the background.
  • color:transparent – needed for browsers than don’t completely crush the text to the point of being invisible. Safari 4 (extremely rare) is an example of such a browser. There may also be mobile browsers than require this declaration. IE6/7/8 don’t recognise this value for color, but fortunately IE7/8 don’t show any trace of the text. IE6 shows a faint trace.

In the HTML5 Boilerplate image replacement helper, we’ve also removed any border and background-color that may be on the element. This makes it easier to use the helper class on elements like button or with links that may included background or border properties as part of a design decision.

Benefits over text-indent methods

The new technique avoids various problems with any text-indent method, including the one proposed by Scott Kellum to avoid iPad 1 performance problems related to large negative text indents.

  • Works in IE6/7 on inline-block elements. Techniques based on text indentation are basically “broken”, as shown by this test case: http://jsfiddle.net/necolas/QZvYa/show/
  • Doesn’t result in any offscreen box being created. The text-indent methods result in a box being drawn (sometimes offscreen) for any text that have been negatively or positively indented. It can sometimes cause performance problems but the font-based method sidesteps those concerns.
  • No need to specify a text-alignment and hide the overflow since the text is crushed to take up no space.
  • No need to hide br or make all fallback HTML display:inline to get around the constraints of using a text indentation. This method is not affected by those problems.
  • Fewer styles are needed as a result of these improvements.

Drawbacks

No image replacement hack is perfect.

  • Leaves a very small trace of the text in IE6.
  • This approach means that you cannot use em units for margins on elements that make use of this image replacement code. This is because the font size is set to 0.
  • Windows-Eyes has a bug that prevents the reading of text hidden using this method. There are no problems with all other screenreaders that have been tested. Thanks to @jkiss for providing these detailed results and to @wilto for confirming this technique works for JAWS 12 in IE 6/7/8 and Firefox 4/5/6.
  • Like so many IR methods, it doesn’t work when CSS is loaded but images are not.
  • Text may not be hidden if a visitor is using a user style sheet which has explicitly set important font-size declarations for the element type on which you have applied the IR class.

It’s worth noting that the NIR image replacement technique avoids these drawbacks, but lacks support in IE6/7.

Closing comments

I’ve been using this technique without significant problems for nearly a year, ever since Jonathan Neal and I used it in a clearfix experiment. The BEM framework also makes use of it for their icon components. The core idea was even proposed back in 2003 but the browser quirks of the day may have prevented wider use.

If you come across any problems with this technique, please report them at the HTML5 Boilerplate GitHub issue tracker and include a test case when appropriate.

Translations