Browse files

Update CSS image replacement technique

The new technique avoids various problems with any text-indent method.
The benefits are:

* No box of any kind is drawn offscreen, so there is no risk of
  related performance problems in old iOS devices.

* No need to specify a text-alignment and hide overflow since the text
  is crushed to take up no space.

* No need to hide `br` or make all fallback HTML `display:inline`
  because unlike the text-indent approaches, this method is not
  affected by those scenarios.

* Fewer styles are needed as a result of these improvements.

The function of the new CSS is as follows:

* `font: 0/0 a` is a shorthand property that reduces the font-size and
  line-height to 0. The `a` value acts as a font-family. The CSS
  validator complains that using `0/0` in the shorthand `font` property
  is not valid, but every browser accepts it.

* `text-shadow: none` makes sure than any inherited text shadow is
  removed, otherwise it will show over the image.

* `color: transparent` is only really needed in browsers than don't
  completely crush the text to the point of being invisible. Safari 4 is
  such a browser (but extremely rare). Leaving it in for now in case
  there are any mobile browsers that require it. Upon further testing,
  it may be possible to remove this declaration.

Some parts of the pre-existing image replacement technique have been
retained. The border and background resets are useful when using IR on
form submit inputs or buttons, as well as when links use default borders
or backgrounds

Close #1005
1 parent 758eab9 commit aa0396eae757c9e03dda4e463fb0d4db5a5f82d7 @necolas necolas committed Mar 5, 2012
Showing with 1 addition and 2 deletions.
  1. +1 −2 css/style.css
@@ -250,8 +250,7 @@ td { vertical-align: top; }
========================================================================== */
/* For image replacement */ { display: block; border: 0; text-indent: -999em; overflow: hidden; background-color: transparent; background-repeat: no-repeat; text-align: left; direction: ltr; *line-height: 0; } br { display: none; } { border:0; font: 0/0 a; text-shadow: none; color: transparent; background-color: transparent; }
mathiasbynens Mar 6, 2012 H5BP member

No space after border:!?!!11

necolas Mar 6, 2012 H5BP member

I know :( Whoever pushes something next can fix that.

/* Hide from both screenreaders and browsers: */
.hidden { display: none !important; visibility: hidden; }

56 comments on commit aa0396e

necolas commented on aa0396e Mar 6, 2012

This method was devised based on the white-space hiding that @jonathantneal and I used in an experiment on containing floats. I've been using it for image replacement in production ever since and it has performed well and even avoids certain IE7 bugs when used with display:inline-block elements.

I've subsequently found that an early version of this method was documented as far back as 2003:

The color: transparent consideration was suggested by @chriseppstein; we could do with some mobile testing to find out if it is necessary. (edit: IE6 needs it anyway)

The super-short font-family a in the font shorthand property is a clever idea taken from the BEM implementation of this method.

And thanks to @scottkellum for sparking another discussion about IR techniques.

If you find any problems with this method, please open an issue about it. Thanks




Ahh that's nice. I like it!



Nice touch ;)




No problems with SEO ?

SelenIT commented on aa0396e Mar 6, 2012

What about "CSS on, images off" scenario? I believe it can still appear for many slow connection users. Is it not considered an accessibility problem any more?


Are there any accessibility issues when setting font-size to 0? Thought I read somewhere that some screen readers have problem with that...

necolas commented on aa0396e Mar 6, 2012

What about "CSS on, images off" scenario?

It's no better or worse than any other IR method that needs to work in IE7 or IE6. The only method I know of that works with CSS on and images off is NIR, but that is IE8+

Are there any accessibility issues when setting font-size to 0? Thought I read somewhere that some screen readers have problem with that...

VoiceOver didn't have any problems with it in my tests. If you know of any research on contemporary screenreaders that shows it is a problem, please share it with us.

SelenIT commented on aa0396e Mar 6, 2012

There is a possibility to emulate NIR method in IE7- by inserting <img>s with a one-time css expression, isn't it?

joahua commented on aa0396e Mar 6, 2012

For those who have avoided this in the past, it's probably because of an old IE5 bug. It considers font-size:0 to be 1px. This was apparently fixed in IE5.5 (but possibly still affected IE5/Mac?). There's also a Mozilla bug that relates to this, fixed in 2002.

Thankfully both of those are but a distant memory today!

necolas commented on aa0396e Mar 6, 2012

@joahua IE6 also seems to consider font-size:0 to be 1px


Some browsers also have a setting for minimum font size. Color: transparent is just a good thing to keep.


Already edited! ;-)

FStop commented on aa0396e Mar 6, 2012

As AlexandreBroudin asks, I also wonder about the SEO implications of this technique. I mainly use it for logos, so that I can have the brand/company/website name in text, for example inside a <h1>, but display logo instead.




I'm really worried about SEO and color : transparent; maybe i shouln't ?

phobia commented on aa0396e Mar 6, 2012

Interesting technique! One thing to be aware with this approach is that it in practise disables the option to have margins in em on the object where the .ir-class is applied. Not a deal breaker, but sensible to keep in mind. :) In such cases one could of course resort to rem where supported.

What about prefixes for the text-shadow?

Calvein commented on aa0396e Mar 6, 2012

@phobia There is no prefixes for text-shadow (yay \o/).

Wilto commented on aa0396e Mar 6, 2012

Tested in VoiceOver (Safari 5, Chrome 17) and JAWS 12 (IE 6/7/8, Firefox 4/5/6) with no problems whatsoever. Great stuff, guys.


Nice solution. Definitely should start using this method.

necolas commented on aa0396e Mar 6, 2012

Turns out IE6 leaves a 1px faint trace of the text because color:transparent isn't supported by IE6/7/8 (but IE7/8 hide the text properly anyway). So if you to 100% remove any trace of text in IE6, you might have to throw an IE6 hack in there.

necolas commented on aa0396e Mar 7, 2012

Thanks to Jason Kiss, who tested against this testcase -, we've got lots more screenreader results. Note that in the results below, <i> refers to the element that was given the IR classes. Here is what Jason said:

Here are some results:

NVDA 2011.3
FF10 all good
IE9 all good

JAWS 13.0.718
FF10 all good
IE9 all good

JAWS 11.0.1476
FF10 positive text indent: text inside <i> is displayed when it receives virtual focus
IE9 all good

JAWS 10.0.1178
FF3.6.27 all good
FF7 positive text indent: text inside <i> is displayed when it gets read
FF10 positive text indent: text inside <i> is displayed when it receives virtual focus
IE8 all good

JAWS 9.0.2191
FF5 positive text indent: text inside <i> is displayed when it gets read
IE8 all good

SAToGo 3.3.32
IE9 positive text indent: text inside <i> is displayed when it gets read

Window-Eyes 7.5.3
FF10 font crushing method: text in <i> is not read
IE9 font crushing method: text in <i> is not read

Window-Eyes 7.2
FF10 font crushing method: text in <i> is not read
IE9 font crushing method: text in <i> is not read

Window-Eyes 7.11
FF10 font crushing method: text in <i> is not read
IE8 all good

Orca 3.2.1 (Ubuntu 11.10)
FF10 all good

  1. I didn't test VO or JAWS 12 as you said you already did those.
  2. I've tested quite a few combinations of SRs and browsers, but not a fully comprehensive and consistent set in each case. Nonetheless, these results identify a few issues:
    A. The font crushing method appears to work fine in all cases except where Window-Eyes is concerned. W-E just won't announce or read the text "hidden" using that method.
    B. JAWS, in more recent versions of FF, at least since FF5 it would appear, causes the text "hidden" using the positive text indent to get displayed when the screen reader reads it. That is, the text is invisible at first, and then, when navigating to it using keyboard, or when reading through the page, it all of a sudden gets displayed (within the box, so is cut off) on top of the red background. This also happens with SAToGo in IE9.

So, is the font crushing method accessible to screen readers? Yes, as long as those screen readers are not Window-Eyes. W-E is known for some wacky bugs. With some additional work, it may be possible to find some kind of workaround. But, if it is possible to confirm that it is a bug, I would personally be inclined to ignore it and that SR: I'm kinda done catering to bugs, esp. with Window-Eyes, that prevent the use of otherwise legitimate and helpful patterns.


+1 to ignoring Window-Eyes unless there’s an elegant solution. W-E is the new IE 5.5.


+1 to ignoring Windows-Eyes for now as well, agreeing with W-E would "prevent the use of otherwise legitimate and helpful patterns."

suprMax commented on aa0396e Mar 7, 2012

What about text selectability? Mb add user-select: none;


I had to ditch this method and go back to the old when using em's, of course.


What's with this craze to adopt the new shiny just because? To be able to use cool-looking code like "0/0 a"?
With poor IE6 support and breakage in one of the top screen readers (in terms of market share), I wouldn't call this a "best practice" at all.


@sjelfull Why did you ditch this and go back to the old method? What went wrong with this method?


I don't feel totally comfortable ignoring Window-Eyes as those users may need the text to read more than anyone. The market share may not be significant but it is a market with few other options.

necolas commented on aa0396e Mar 8, 2012

@mrazzari The commit message and related issue explain why this method was considered. The text-indent methods are completely broken in IE6/7 when used on inline blocks. Windows-Eyes's market share is not as high as you suggest - - and Jason's opinion on the matter is informed. Also, your condescending tone and unfair characterisations are not appreciated. There is no reason why this project should not push changes to the master branch and respond to any polite and helpful feedback from others before cutting a stable release.


Why did you ditch this and go back to the old method?

-> "using em's"


@necolas you're right, and I apologize for the tone of my comment.

I'm just very pissed with the general trend to just pretend IE6 users don't exist. I know you and @paulirish have said, in previous issues here and in your blog, that h5bp is committed to supporting IE6 for the time being. That's why this change landing on master caught me a bit off guard. So, again, my apologies.

That said, W-E's market's share is diminishing, but it's still very relevant. (In particular, it seems, for "business" users.)

I think everyone agrees that minor layout differences are OK, and even major ones if talking about IE6. But having visual glitches over a site's logo or icons (where .ir is most useful, and glitches more visible), seems like too risky an assumption to be considered a best practice.

Re: inline-block, since it needs workarounds to work in oldIE anyway, I'd assume you're CSS-savy and can fix your text-indent conflicts.
The new method, OTOH, would inflict IE6 bugs on the not-so-savy crowds.

1% (other sources cite 2-3% as well) seems like a low enough margin to begin accepting less-than-ideal ie6 solutions that improve performance for the higher-margin bases (Chrome 16 and 17 together hold ~32.4%). I'd say Firefox 3.6 is the browser to really worry about (fortunately not in this case, though.)

I don't think there's anything wrong with writing "shiny" code as long as it's valid or all browsers work with it. There's a good reason why "0/0 a" is used here; it is the shortest version of code, and if it becomes a standard, people will recognize it for what it does, not what it semantically means.

IE6 users shouldn't be ignored, true; however, there is a hierarchy of importance in these decisions.


@jcutrell no need to quote stats.
We totally agree on IE6. I just think that this crosses the line from less-than-ideal to below-acceptable, if you have glitches over those visual elements that are key to your brand (logo, icons, nav).
Also, I hope we don't start quoting low % figures to dismiss a11y next ;)


@scottkellum as @necolas mentioned, i'm setting the dimensions in em's. With the font-size set to 0, the width/height is equivalent to 0x0.


@sjelfull would you tell me how you are using ems? I am interested in knowing more about your use case.

In my projects, I use ems only when I am also using background-size. I have found that because the image is sized in pixels it is better to css size it in pixels too.

necolas commented on aa0396e Mar 9, 2012

@jonathantneal e.g. Using ems for margin/padding of the element itself.


@necolas ah, now I understand. That was simple. That makes sense.


I have two questions:

  1. is Window-Eyes right or wrong? Because if it is the former, other ADs may change their behavior in the future.
  2. is there any research about font-size:0 regarding SE? IR techniques are mostly used for headings, so any SE issue with this approach could be a real problem.

Also, it should be noted that the technique fails with image off. Imho, this should be disclosed as many users believe that anything H5BP related is best practice.


it should be noted that the technique fails with image off

It already is in the article I wrote about the technique. No different to many other IR techniques.


It already is in the article I wrote about the technique.

I'd think many people will use this without knowing about your article. No?

No different to many other IR techniques.

There are a few that are more accessible than others (sorry for the shameless plug:, but in any case the point is to make sure users are aware of the "issue".

I just checked your article, it says:

Windows-Eyes has a bug that prevents...

Are we sure this is a bug? With the exception of the "off-screen" method most other techniques used to hide content from sighted users do it also for SR users, no? For example display;none and visibility:hidden or even height:0;overflow:hidden if I recall

Finally, what about Search Engines? It was said using color:transparent or using matching foreground/background color was a bad idea. Font-size:0 could fall in this category, no?


I've found 2 more IR bugs in IE7, one thanks to a comment on my blog:

  1. The font-crushing method can show a small trace of text in IE7 if there is any bottom-padding on the IR'ed element.
  2. The positive text-indent method doesn't work in IE7 if the background image is horizontally centered.

Regarding earlier IE6 comments - for anyone interested in global & by-country IE6 stats, Microsoft's own is by far the best source I know of, whereas W3Schools traffic is highly biased towards web developers, so its stats are not representative of the general/global population of web users.


As of February of 2012, 7.1% of the internet users in the world are likely running Internet Explorer 6. Of that percentage, more than half of those users are in China. Within China, nearly a quarter of all internet users are likely running Internet Explorer 6.

... In China, over 90% of software is pirated, most Chinese users never connect to Windows Update or even upgrading their web browser... (Also) the China Government’s IT department registration website (MIIT), is IE6 only. Without IE6, authorities cannot file their registration information. Online banking in China is also strictly a Windows and IE6 love affair. They usually used ActiveX login system, any western companies setting up their brunch office in China, must install IE6 in their Windows PCs, otherwise no work can be done through any of the major Chinese banks. The same case for those China major online shopping sites, which require their customers to use IE, rather then other web browser’s options. Kip Kniskern for on March 16, 2011


had an instance of ie7 needing color: transparent to kill a small trace of text on an element without bottom-padding.


color: transparent is easily overruled. A lot of people define colour with selectors of higher specificity than 10 – for instance, colour is often inferred from inheritance (.footer a {color: different}).

I'd been using an old fork of mine with different cosmetics until yesterday, but this fails a fair bit for me now. Really surprised no one else has found this actually. What test cases are you guys using?

Sticking an important on it is warranted IMO…


Hmm. Not seeing the forest for the trees, it took me until today to realise that, of course, font properties are specified all the time (which again nerfs this). In fact both crucial properties are incredibly commonly used for their legitimate intended purposes (as opposed to this hack), making this incredibly prone to superseding (whereas overflow: hidden and text-indent: don't cascade).

The other failing with this is when color is specified for ::selection

So personally, I believe this regresses on all count. Apart from the iOS box performance issue (significant?), the other issues were pretty much code aesthetic – shall we mark this as a bug and revert back to the version that worked?


See #1108

Zae commented on aa0396e Aug 23, 2013

I'd like to add, I added !important behind the color statement to force the color to stay transparent in case it's overwritten by some other statement overriding the color. (:hover on a element for instance).

This fixed a bug that caused the text to become visible on safari.

Grsmto commented on aa0396e Sep 20, 2013

@Zae +1 for this. Solved my problem with a pseudo element changing color on hover state.


Almost certainly has a negative SEO impact. Why not use Jonathan Snook's clip method?

drublic commented on aa0396e Apr 7, 2014

@booshtukka it's not in use anymore. Do you have any reference that this has a negative impact on SEO?


It's well known that setting font-size to zero is penalised by search engines. It's also very well known, that having text colour the same as background colour is penalised by search engines – if I were writing a search engine, I would put transparent text in that category. Either way "color: transparent; background-color: transparent;" is setting the text to the same colour as the background, so even the 2002 algorithms would see that as a black hat technique. Spend ten minutes searching and you will only find evidence that agrees with what I am saying.

Also, the current version of VoiceOver doesn't read this at all. Setting a font-size of zero tells them it there is nothing there to read. This code for example:

    <div class="ir">2</div>

…reads "1 3", not "1 2 3".

The latest WebAIM survey ( shows that WindowsEyes is the fifth most popular screenreader, with 7% of the votes. This figure will grow since it is now distributed free with Office. I wouldn't be comfortable accepting that those users will not be able to read the text.


The latest version of boilerplate appears to use the clip method, and have no .ir class anymore. In which case that's great. And I'm not sure why I am commenting on this page. :)

alrra commented on aa0396e Apr 10, 2014

And I'm not sure why I am commenting on this page. :)

@booshtukka don't worry, comments like that are always welcome!



Please sign in to comment.