1 Mar 2012 12 pm eastern

Replacing the -9999px hack (new image replacement)

IN THE BEGINNING was FIR, AKA Fahrner Image Replacement (note that one of the following links returns a 404):

The Daily Report’s 2003 redesign uses (and our book explained) an image replacement technique intended to combine the benefits of accessibility with the power of graphic design. We christened this method Fahrner Image Replacement (FIR) in honor of Todd Fahrner, who first suggested it to us. Douglas Bowman’s tutorial popularized the technique, which was first developed by C. Z. Robertson in 1999. (Robertson, Fahrner, and Bowman each developed the idea independently.)

Preceding web type by a decade, Fahrner gave us the ability to use fonts other than Verdana and Georgia on web pages (i.e. to set type in Photoshop and export it as an image—an ancient web design practice) but to conjure these images of text via semantic HTML markup (the words the text pictured, set in appropriately structural HTML elements).

Then came Phark’s Accessible Image Replacement, which improved on the Fahrner method by avoiding edge case failures and accessibility problems inherent in FIR. The principal aspect of the Phark method—the part of it all of us remember and use to this day—was this little piece of code:


So popular was this method, we made a tee shirt out of it, and it sold, baby, it sold.

But despite its enduring popularity, Phark has drawbacks of its own: chiefly, a performance hit caused by the need to draw a giant 9999px box offscreen. (Yes, the browser really does this.)

My friend Scott Kellum, design director at Treesaver, has now sent me this refactored code for hiding text, which I hereby christen the Kellum Method:

.hide-text {
text-indent: 100%;
white-space: nowrap;
overflow: hidden;

  • Really long strings of text will never flow into the container because they always flow away from the container.
  • Performance is dramatically improved because a 9999px box is not drawn. Noticeably so in animations on the iPad 1.


Filed under: CSS, State of the Web, The Essentials

147 Responses to “Replacing the -9999px hack (new image replacement)”

  1. Susan said on

    Seems like this would be a good alternative method for skip links too. In a little test case, it seems to meet req’s in the same manner.

  2. Chris Cox said on

    I always used ems instead of px so that edge-case zooms wouldn’t bring text onto the page, but that’s brilliant.

  3. Kendall said on

    Thanks for the tip!
    I just implemented this on an element “.site-name a”, which I was replacing with a background image. However I also had to add “cursor: pointer;” for the correct cursor to come up.

  4. Derrick said on

    Great way. Once it is widely supported, I’m using it.looks clean as well

  5. Thomas McGee said on

    I always used the ems as well instead of px for this value, but I’m not sure why I never thought to use 100%—that makes way more sense. Guess I’ll be changing my ways! *bookmarks the page* :-)

  6. Alex Lande said on

    I had no idea there was such a performance drawback to the -999em technique. Going to try this next time the need arises.

  7. Luke said on

    All hail Kellum.
    T-shirt please. I will buy it. Also, said shirt should hide belly overflow.

  8. Matt Radel said on

    I honestly didn’t know that the browser still drew a 9999px wide box. That’s an awesome tip, thanks for sharing!

    Also, anyone still selling those -9999px tees?

  9. Patrick Haney said on

    I always thought there was a better way to handle this, but never really thought about the enormous box the browser had to draw or the performance hit involved. I’ll definitely start using this method over the other, especially since I was using -9999em instead of pixels quite often, which would create an even MORE ridiculously large box.

  10. Jeff Croft said on

    Brilliant. Amazing that, nearly 10 years later, we’re still finding ways to improve on something like this.

  11. Andrew Ckor said on

    Wow, imagine those control buttons on a huuuuuuge listing!!
    Number of list items * 9999px = xxxxxxxxxxxx px!!!

    Great approach. Thanks for sharing.

  12. richtaur said on

    Was anybody else expecting some kind of new CSS3 fanciness? I believe these rules were supported back when the original hack was made, which I find quite surprising!

    Good stuff, thanks, consider my habit changed.

  13. Bart said on

    What if you used overflow:hidden on the body or html for the -9999px trick? Would it still draw a > 9999px box?

  14. Little Spark VT said on

    Didn’t know the browser would draw a gigantic box for the text. Thanks for the tip!

  15. Ain said on

    Works like a charm! Thanks for the tip!

  16. John Lascurettes said on

    Very interesting. We’ve been tweaking our app to wring every bit of performance improvement out of IE7 we can. I wonder how much difference it will make.

    I’m assuming the DOM element still needs to be set to block or inline-block for the overflows and and indents to take proper effect.

  17. Replacing the -9999px Hack » Mackinations » Mack Richardson's Thoughts on Web Design, Life and Superheroes said on

    [...] Read More at Zeldman.com [...]

  18. Michael said on

    Great Snip! Thx

  19. Scott said on

    Thanks for posting this. This method until something even better is discovered.

  20. Tiger Beasley said on

    Very interesting. I’ve been tweaking our app every bit of performance improvement out of IE8, Chrome, Safari and Firefox. I wonder how much difference it will make if I tune it to all available browsers. Just kidding. it is very interesting tho what you said:-)

  21. chauffeur said on

    great topic, I very much hope someone here will tell us more info!

  22. James John Malcolm said on

    @Patrick It’s true they were all in the spec, but the nowrap one didn’t work properly if I remember correctly.

    How’s the accessibility impact of this method? Keyboard nav?

  23. Ethan said on

    Wow, crazy. Go Scott!

    This is the first I’ve heard of negative text-indent incurring a performance hit. Is there somewhere I could read about that?

  24. Romina said on

    Wow, what an elegant solution! I had no idea the -9999px took up so much performance. What tools or plugins do you use to monitor that?

  25. Scott Kellum said on

    I went ahead and created a side by side site to test the performance: http://lab.pgdn.us/hidden-text-performance/

    @Ethan, This is the best 43min I have ever spent learning about optimizing the performance of my CSS: http://www.youtube.com/watch?v=xuMWhto62Eo

  26. Bart said on

    How do you test the performance of this? It’s browser rendering speed…right? @Scott Kellum – I don’t see any difference in your example.

  27. Scott Kellum said on

    @Romina, the Webkit nightly has a CSS profiler. I think Opera Dragonfly does as well but I haven’t really gotten into it. Performance is probably a little different on different engines.

    Here are my results: http://yfrog.com/kgqzwp

  28. Ian Lloyd said on

    Damn, and there I was thinking I was being extra careful by using -30,000px, not aware that I was being 3x less efficient. Because, y’know, that 10,000px wide screen *might* have come along in our time, too :)

  29. Paul Irish said on

    Over at the HTML5 Boilerplate project we’re taking a look at this. So far, we’re unable to reproduce the performance advantage on modern hardware. It may just join the ranks of css gradients and box shadows as things to avoid on old hardware before things like the webkit-box-shadow perf fixes went in. http://wkb.ug/22102

    https://github.com/h5bp/html5-boilerplate/issues/1005 We’re still investigating…

    But to put this into perspective, removing one script tag from your head would have, at a minimum, around  300x more impact than this reflow optimization. But if you’re optimizing reflow on iPad 1 devices, then it’s certainly worth looking into.

  30. Benjamin Bixby said on

    Great tip! Thanks!

  31. Kev Adamson said on

    Seems like a more elegant solution, but I’m grateful for Paul’s comment above, in which he gives a very “real world” analysis. We’re all often guilty of picking out wallpaper, whilst failing to notice the room is on fire :P

  32. Brockdin Barr said on

    T-Shirt: “I practice the Kellum Technique”

  33. Replacing the -9999px hack (new image replacement) – Jeffrey Zeldman Presents The Daily Report » Web Design said on

    [...] Replacing the -9999px hack (new image replacement) – Jeffrey Zeldman Presents The Daily Report [...]

  34. Nacho said on

    Thank you, this it’s a very interesting trick. Thanks for sharing!

  35. Kelley Curry said on

    Wow. I didn’t know about the big box and (apparently arguable) performance hit, but I feel better knowing that @beep didn’t either. :) I will definitely be trying this out.

  36. Version 1.0.0 Custom Login Pro Officially launched - The Frosty said on

    [...] Updated: CSS visibility hidden style from -9999px to text-indent: 100%; white-space: nowrap; @ref: zeldman. [...]

  37. Ryan said on


  38. Links – March 1, 2012 | zota said on

    [...] Replacing the -9999px hack (new image replacement) – Jeffrey Zeldman Presents The Daily Report text-indent: 100%; white-space: nowrap; overflow: hidden; [...]

  39. dusoft said on

    What’s this good for these days? What about downloadable fonts, Google fonts API etc.? There is no sense in trying to refresh outdated techniques.

  40. Jamie Hill said on

    One of those “why didn’t I think of that!” moments. Around a decade of using the negative text-indent without questioning it… this new tequnique is much nicer.

  41. Carl said on

    I really like the thinking behind this. Since it does affect things like the iPad 1 (which I have) I am keen to optimize, however, i’m struggling to get it to work when using it on absolutely positioned elements, but that could be something at my end :D

    Now I just need to go through all my other bits of code and remove the -99999px (yep extra 9… I was future proofing!)

  42. Trevor Saint said on

    Thanks for this trick. I will certainly use it for future projects.

  43. Jeffrey Zeldman said on

    @dusoft asked:

    What’s this good for these days? What about downloadable fonts, Google fonts API etc.? There is no sense in trying to refresh outdated techniques.

    Glad you asked! Obviously, you wouldn’t use it to replace headline text. You can do that with web fonts.

    If you “just had to” use a typeface which had no licensable web font equivalent, you still wouldn’t use this method: there are other (also outdated) methods around like SIFR and Cufon that let you replace text with a font that’s not otherwise available on the web—but those outdated techniques, great in their day, also have downsides: SIFR won’t work in a fair number of important mobile contexts; Cufon, because of its technological implementation, probably violates the license agreement that came with your font. If I “just had to” use a specific font that was only available to me via SIFR or Cufon, I’d almost certainly suck it up and pick a different font.

    So what is this technique good for? Well, you might use it with a logo that is text-based. Most logos are, and to try to reproduce an actual logo using web fonts and tortured CSS would be an interesting design class exercise, but not something you’d actually do on a professional web page. In some cases, that logo can be served as a straight image with alt text inside an appropriate HTML element — such as the type treatment at the top of this site in its current fixed-width form.

    But say you are creating a responsive design, and need to switch out differently sized logo images depending on the context in which they’re viewed. Ah! Then you would use Scott Kellum’s technique and be very, very grateful for it.

  44. Ollie Wells said on

    Lovely. Whats the cross browser support on this?

  45. Mark McDonnell said on

    Personally this is more confusing that text-index:-999em as it’s harder to remember (yes I know you’ll have a standard CSS file which this would always be included but if you’re working on someone elses code and you wanted to remember that css trick to hide text then text-index is much easier to remember).

    Also this seems like a proper micro-optimisation for a real edge case scenario but it’s presented as the defacto way to do this type of thing from now on which I think isn’t how this should have been presented.

    Just my opinions and I may be wrong but that’s my input.

  46. adokara said on


    How can i mesure the benefit of this technique ?

  47. Dan Rubin said on

    Fantastic. Thank you so very much for sharing (feels like 10 years ago again!)

    @Paul Irish: Even if the performance improvement is minor (and I believe you), this feels like a cleaner, less-hacky solution to the problem. The performance increase on older devices, iPad 1, etc. is a (responsible) bonus.

  48. Benjamin said on

    Exactly the same issue than the negative text indent technique: nothing is visible for a user with CSS enabled but images disabled. Accessibility, anyone?

  49. Paul Robert Lloyd said on

    In my early experiments using this new technique, it fails in cases where padding has been applied to the element being replaced. Perhaps I shouldn’t be adding padding in this instance anyway, but I thought it was an issue worth highlighting.

  50. Javier Gala said on

    Thanks for this! It looks much more meaningful than throwing our text to the infinite and beyond (on the left) 8-).

    Anyway, I had this minor problem with it: I used it to replace an “about me” logo and found some of the link text showing (part of the “A” from “About me”, as you can see in the following capture).

    (part of an “A” is showing just before the first line on the upper right hand).

    I understand it has to do with me applying some padding to the tag trying to achieve my intended result. Sorry if I am a bit of a newbie when dealing with CSS, but I played with it and it seems the “overflow: hidden” property is making text-indent to use width instead of that of ‘s parent element. I used text-indent: 150% to “kick” it a little to the right until I find a perfect solution.

    So, my advice would be to be careful with this replacement if you are applying padding to the element, or use a higher text indent to prevent it.

  51. Jack Smith said on

    Would it be worth adding ‘box-sizing: border-box;’ to fix that glitch Paul mentioned above? Still some browser support issues mind…

  52. Friday Focus 03/02/12: Tentacular | Devlounge said on

    [...] Accessibility – Replacing the -9999px hack (new image replacement) “My friend Scott Kellum, design director at Treesaver, has now sent me this refactored code [...]

  53. Curt Grymala said on

    Thanks for sharing. I’ve been using a similar method of image replacement for a few years, but instead of using the text-indent property, I’ve always used top & right padding on a fixed-size element. I will definitely be playing with the method you shared above to see how it improves things.

    To add another similar concept to your list of potential places to use this sort of image replacement, I find myself using it quite often to create text links to things like Facebook, Twitter, etc., then replacing the text in the links with an appropriate icon or button.

  54. Erik Vorhes said on

    One of the promising things about advanced OpenType features coming to the web is that companies could commission a typeface that automagically becomes their logo when the company name is typed. The file size would be pretty small (you wouldn’t need a full character set), and it’d scale well, regardless of context.

    But! — there aren’t many browsers that support that stuff (yet). Until there’s much wider support, this image-replacement technique looks like the way to go.

  55. Replacing the -9999px hack new image replacement – Jeffrey Zeldman Presents The Daily Report « CagontolCSS… said on

    [...] Replacing the -9999px hack new image replacement – Jeffrey Zeldman Presents The Daily Report. Me gusta:Me gustaSé el primero en decir que te gusta esta post. [...]

  56. Jason O'Brien said on

    I tried to break this method by using absolute positioning and applying padding, but it holds up for me, at least on Webkit. Those that are having issues, what OS/browser are you running?

  57. Scott said on

    This is an improvement, but I’ve honestly never found a valid reason to use the -9999px method or any other text hiding technique. Google penalizes sites for hiding text, it is thought of a “untrustworthy”. If the purpose is SEO, why not just add a title attribute to the image?

  58. Scott said on

    What I meant to say was, if the purpose is “accessibility”, why not use the title attribute, which will still be read by screen readers.

  59. Josh Broton said on

    Honest question (don’t have an iPad near me to test), but wouldn’t this be accomplished by throwing the text into a second span and add this to the css?

    #new > span > span { opacity:0 }

    Like I said, no time to test… just thinking out loud.

  60. Hugh Roper said on

    This is great, and i’ll use it for a little while, but still has accessibility issues (text doesn’t display when images are turned off).

    When I have more time I’m going to finish getting the same results with the :before and :after pseudo elements (inspired by Chris Coyier). I’ve used a pseudo element with a background image to cover the text (and styled the text not to wrap). Works in webkit. Need to debug elsewhere. If you get it dancing everywhere, share the love.

  61. ConnyLo said on

    T-Shirt: »100% is more«

  62. Michael K said on

    [novice question alert]

    With respect to Jeffrey’s example and these techniques in general, here’s something I’ve always wondered about but never bothered to ask:

    What’s the drawback of just including the text of the logotype as an or tag right before the logo’s and then hide that text element with CSS, then if you need to, make the responsive with media queries or javascript?



    [Note: I dunno if for this example another one of the H5BP classes like `.visuallyHidden` or `.invisible` would be more appropriate.]

  63. Mantish said on

    Great tip.

    Seems pretty good. How does it compare to the modified NIR method http://nicolasgallagher.com/css-image-replacement-with-pseudo-elements/

  64. Rick Lowes said on

    Would be interesting to understand both the SEO and accessibility impacts of this approach.

  65. Marcus Overton said on

    Sweet! This fixes an issue I’ve been having with the Phark method causing flashing in Safari.

  66. Scott Kellum said on

    After much deliberation over here: https://github.com/h5bp/html5-boilerplate/issues/1005#issuecomment-4293007

    Jonathan Neal suggested a method using font: 0/0 serif; and things seem to be settling on this —

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

  67. Stephanie Hobson said on

    I’ve been doing something similar but less object oriented. It requires you know the height and width of the box you’re replacing but with most image replacement you do.

    I find I use image replacement the most these days when inserting images from sprites. Text on the page serves the function of alt text. Using it now for a series of icons:

    10 Votes

    21 Check-ins

    background: url(icon-sprite.png) no-repeat;

    .meta-checks .meta-icon{background-position:0px -18px;}

  68. Stephanie Hobson said on

    Damn, lost my HTML. I never have got the hang of coding in comments.

  69. Dalibor Sojic said on

    Here is another, similar technique: http://right-sock.net/tips/seo-friendly-hiding/

  70. Nouvelle méthode de remplacement d’image en CSS said on

    [...] Nouvelle méthode de remplacement d’image en CSS Pour remplacer du texte par une image avec CSS, il existe au moins neuf méthodes, dont deux ont été largement utilisées par les intégrateurs web. Vous trouverez à la fin de l’article une dixième méthode — alliant performance et accessibilité — qui nous vient tout droit de chez Jeffrey Zeldman. [...]

  71. The Kellum Image Replacement Technique, or bye -9999px | TTI COM Visual Media said on

    [...] Instead of the familiar of using left:-9999px, from the excellent zeldman.com: [...]

  72. Alex Lemanski said on

    While I think this is certainly and interesting approach, I have some concerns with the accessibility. In some, if not all, cases when overflow: hidden; hides the content of the element this is applied to from screen readers. In most cases where I use image replacement, I still need the text to be accessible (e.g. call to action buttons set in Gotham). See Aaron Gustafson’s A List Apart article, http://www.alistapart.com/articles/now-you-see-me/.

    Has anyone tested this with a wide battery of screen readers or other accessibility devices?

  73. Håkan Save Hansson said on

    Interesting. Thanks!

  74. Today’s Readings | Aaron T. Grogg said on

    [...] This is great! Even with the above news about web fonts, the reality is that the graphic text is still around, and might even be better for performance if you’re talking low-bandwidth (when you could download a single sprite for multiple fonts rather than multiple font files), but on those mobile devices (I’m looking at you, iPad!), sending your in-page, semantic text off-stage by -9999px absolutely kills you! Nicely done, Mr. Kellum! Once more, seems like I have a lot of CSS files to update… [...]

  75. Már said on

    @Zeldman it might be good to add

    letter-spacing: -.4em;

    …to the mix, to contract the box-size even further.

  76. Dave said on

    @Scott kellum won’t google penalise the use of Jonathan’s suggestion as hidden keyword stuffing!?

  77. Dirac said on

    CSS, intuitive as always.

  78. Jakub Kejha said on

    Damn it, this is genius. I’m getting out of the bed and I’m trying it right now.

  79. Franke said on

    A neat little replacement. Thanks for sharing

  80. Thomas Scholz said on

    Another note on accessibility: Besides the screen reader problems – people who don’t get images will not see the text too.

  81. Activity Ledger (beta) for March 3rd | octidextro.us said on

    [...] Shared Replacing the -9999px hack (new image replacement) – Jeffrey Zeldman Presents The Daily Report. [...]

  82. Jeffrey Ridout said on

    It won’t be long before older browsers like IE7 will start to disappear.
    When that happens I’ll start using a modified version of Nicolas Gallagher’s method for applying multiple backgrounds to an element. (http://nicolasgallagher.com/multiple-backgrounds-and-borders-with-css2/)


    Company name…


    h1.logo {
    position: relative;
    font-size: 34px;
    line-height: 34px;
    width: 85px;
    height: 34px;
    padding: 0;
    z-index: -1; /* The z-index would normally be 1 for the content, but we want it to be behind the image. */
    h1.logo:after {
    content: ”;
    position: absolute;
    background-image: url(‘company_logo.png’);
    background-position: 0 0;
    z-index: 1; /* The z-index would normally be -1 for the additional background, but we want it in front of the image.
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;

    Using this, the text is still visible and valid even if the image fails to load.

  83. Jeffrey Ridout said on

    HTML was stripped…
    See Fiddle: http://jsfiddle.net/xHqvL/

  84. CSS: neue Methode um Text zu verbergen | WordPress & Webwork said on

    [...] den Nachteil, dass der Browser eine knapp 10.000 Pixel große Box erstellen muss, daher hat Zeldman eine neue Methode [...]

  85. Ben Bodien said on

    Does anyone have a citation or more information for the bit about “the browser” “drawing a box” or otherwise incurring a rendering overhead for elements positioned outside the viewport?

    Info on this is a little tricky to come by, but I’m fairly sure that Webkit at least optimises out any off-viewport elements during rendering. I’d be surprised if Gecko doesn’t do likewise.

  86. David Holloway said on

    Thanks for this neat little replacement idea. Although I’m having issues getting this to work in Firefox 10.0.2. Works fine in all other browsers. Any ideas why?

  87. Dave Bowker said on

    I’ve a big client site where I have 100+ instances of text-indent:-99999px; which I switched over to (+)100% last Friday, without overflow or whitespace property. First review saw not all instances with explicit height and width get pushed to the right extending the window. I’m sure this would of been fixed with the extra overflow and white-space declarations, but switching the (+)100% to (-)100% meant that it worked just as the -99999px rule did, without the extra properties.


  88. David Holloway said on

    Thanks for sharing this nice new way of declaring an image replacement. Working well in all browsers except firefox for me. Any ideas why?

  89. -9999em. 9 danke. | undkonsortenBlog said on

    [...] Hier noch der Artikel von Jeffrey Zeldman. [...]

  90. Chris said on

    What’s wrong with height: 0; padding-top: 20px; overflow: hidden; ???

  91. Ben Bodien said on

    Following up with some research findings: this excellent talk on webkit performance optimisation by Matt Seeley at Netflix:


    At 35:20, Matt mentions discovering that the render layer for something that’s on screen with a massively negative text-indent value is calculated to be that text-indented size.

  92. Dominick Pham said on

    Does anyone else feel that setting overflow: hidden is a dangerous thing to do? Any container using that property should be the exception and not the norm, there’s no reason to assume that just because you want to hide the overflowing text, you also want to hide everything else that overflows. This is what the -9999px text indent, default overflow gave you.

  93. Phil Ricketts said on

    I wonder if font-size:0 would be better? I’m guessing it’s a no-no due to screen reader behaviour.

    I suspect {color:transparent} would be better altogether.

  94. Weekly Design News – Resources, Tutorials and Freebies (N.123) said on

    [...] icon fonts, UI kits, vectors and themes.Android Design – Learning how to design Android appsReplacing the -9999px hack (new image replacement)Build a Contacts Manager Using Backbone.jsHow to use FlexSlider with HTML5 Boilerplate, [...]

  95. Joel Drapper said on

    Why not just do this?

    .text {
    overflow: hidden;
    width: 100px;
    height: 0px;
    padding-top: 100px;
    background: url(‘image.png’);

  96. egiova said on

    This is a very smart solution. Even if you need an extra declaration.
    It seems to work in FF too (I tested it in Chrome, FF, Safari and Opera). Pending on multiple devices.

  97. Another CSS image replacement technique – Nicolas Gallagher said on

    [...] 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 [...]

  98. Nimsrules said on

    This one’s an innovative technique. Shall surely implement it in my next project. Thanks for sharing!

  99. Theo said on

    Thanks for the great and useful snippet!

  100. Ted Goas said on

    I wouldn’t be surprised if y’all saw this already, but Nicolas Gallagher posted another CSS image replacement technique that does not require large text boxes, text-indent, or overflow. Though the method is not without its own drawbacks, also listed.

  101. Beth Budwig said on

    So I hate to be that person, but… it doesn’t seem to work in IE6. Anyone else seeing the text showing? I’ll try to revisit this when I have time and figure out what’s not working. (Yes, we still support IE6 — we have paying customers whose sole browser is IE6 and we are not in a position to make them upgrade.) (Yes, that sucks.)

  102. Mark said on


    I never used the -9999px. I was a visibility:hidden person. I would wrap a span inside my [a] and hide the span, but this is much better. More semantic code, no need for extra tags to hide it.

    Brilliant. Except now I’m ashamed of every site that I have out on the net, because it’s all archaic code.

  103. Larry Botha said on

    The folks over at html5 Boilerplate have updated their image replacement with a version which doesn’t require any text-indent:


  104. William said on

    And what do you guys think of this technique ?

    With an image of 30px high :
    .foo {

    Anyway, thank for sharing your snippet :)

  105. Innovative and Useful CSS3 Techniques And Tutorials | webexpedition18 said on

    [...] Fun CSS Image Effects You Can Copy and PasteCSS3 Ordered List StylesCSS3 Image Styles – Part 2Replacing The -9999px Hack (New Image Replacment)Orman Clark’s Vertical Navigation Menu: The CSS3 VersionCSS Social ButtonsStyling Form Elements [...]

  106. Revision 61: HTML5 Please API, Boot to Gecko, Image Replacements | Working Draft said on

    [...] der heilige Zeldman als auch Nicolas Gallagher kredenzen uns neue Techniken. Wir sind so mittelbegeistert, denn die Vorteile (gleichwohl vorhanden) halten sich doch [...]

  107. Capi Etheriel said on

    letter-spacing: -5em (for safety, usually -3 should be enough) might work without compromising performance as well. We need more tests.

  108. Jérôme Coupé said on

    Good addition to the toolkit but does not solve the CSS on image off scenario.

    Still like the Gilder/Levin Method for non-transparent images: http://www.mezzoblue.com/tests/revised-image-replacement/ or Nicolas Gallagher method building upon it: http://nicolasgallagher.com/multiple-backgrounds-and-borders-with-css2/

  109. CSS | Pearltrees said on

    [...] Filed under: CSS _________________ Performance is dramatically improved because a 9999px box is not drawn. Noticeably so in animations on the iPad 1. Replacing the -9999px hack (new image replacement) – Jeffrey Zeldman Presents The Daily Report [...]

  110. Jeffrey Zeldman said on

    My eyes are crossed.

  111. Jason said on

    @Joel & @William that is also the method I use. I would love to get feedback on it. I call it the Feux Sprite method because of how closely it resembles moving sprites behind the box model.

  112. Hugh Guiney said on

    I tried this in Chrome on a H5BP site and got a mysteriously off-center image; inspecting revealed extra white space to the right that could not be removed by zeroing margin or padding, nor by shifting the background coordinates over—as soon as the image hit that area, it was cut off; changing overflow had no effect either.

  113. Sharpen Your Professional Toolkit » SitePoint said on

    [...] out that changes the way we think about an age-old problem. Jeffrey Zeldman just wrote about a new CSS image replacement method Scott Kellum discovered. We’ve been using the -9999px hack for years, but the new method is [...]

  114. Pushpinder Bagga said on

    works like a charm – thanks!

  115. Ian Culshaw said on

    Doesn’t full work in below example.


  116. Ian Culshaw said on

    ignore previous comment, made a typo on white-space!

  117. Mozilla Hacks Weekly, March 8th 2012 ✩ Mozilla Hacks – the Web developer blog said on

    [...] Replacing the -9999px hack (new image replacement) [...]

  118. keith baker said on

    I’ve been doing this for the past couple of years – I had no idea it wasn’t already common place.

  119. Irving Briscoe said on


  120. Thierry Koblentz said on

    As a few people said already, this does not solve the accessibility problem that comes with text-indent. Worse, it may send the wrong message: “this is new and cool, use this from now!”.

    As a leader in the industry, I think you should warn people that even if this is “better” in term of performance, it is still a bad solution.

    Imo, Image Replacement techniques should be evaluated against the problems they solve/address. Fwiw, I wrote something about these challenges a few years back:
    http://tjkdesign.com/articles/tip.asp </shameless plug>

  121. Sylvia @ DzinePOD said on

    This is fantastic. Didn’t realize the old -9999px hack was causing slowness. This is a better way to do it. Thanks!

  122. Roman said on

    According to Scott Kellum, the difference for him was just 0.007 ms. This is 7 thousandths of a millisecond! Those who think that this tip would save them time should refresh their math skills.

  123. Criação de Sites said on

    Thanks for the great and useful snippet!

  124. megawrz said on

    And what do you guys think of this technique ?

    With an image of 30px high :
    .foo {

    Anyway, thank for sharing your snippet :)

  125. Tonpoo said on

    Thanks for great solution. I tested it on IE6 and it worked fine. I’ve made an article about this solution to our company’s blog (in Japanese), insisting on your blog and your friend’s name, of course. I hope it’ll be some help for my friends also.

  126. Glyn Mooney said on

    The amout of times I’ve used similar patters and never thought of doing that. Feel a little institutionalised… Need to be a little more inventive from now on!

  127. Bootstrap 2.0.2 released · Deep Thoughts by Mark Otto said on

    [...] Added mixin for new image replacement technique [...]

  128. Kevin Kirchner said on

    For whatever reason, replacing a link that has an inner span (even though both have text-decoration: none !important) a little blue dot was appearing after the image in Firefox. screenshot: http://files.classyllama.com/bc9abf9a/2012-03-13_0727.png

    I fixed it by simply making text-indent: 101% instead of 100%

  129. iamkeir said on

    Is there a similar idea/technique for the accessible hiding of block elements? I currently use position: absolute; left: -999em;

  130. James Drinkwater said on

    Been looking at some sites that use -9999px for hiding things in FireFox 11’s new 3D viewer, with just the right rotation you can kindof see the hidden elements floating miles off in the distance.

  131. Today’s Readings | Aaron T. GroggAaron T. Grogg said on

    [...] image replacement techniques: http://nicolasgallagher.com/another-css-image-replacement-technique/ http://www.zeldman.com/2012/03/01/replacing-the-9999px-hack-new-image-replacement/ Both are improvements over the old-standard text-indent: -9999px;, especially if you’re [...]

  132. Nouvelle méthode de remplacement de texte par une image said on

    [...] les pertes de performances. Notez que ces dernières affectent également la dernière méthode proposée par Scott Kellum qui vise au départ à améliorer les performances sur iPad [...]

  133. Matthew Boynes said on

    This sounded cool so I started using it. Unfortunately, IE7 (at least, didn’t bother with 8 and 9) doesn’t always play nice with this. Specifically, I was using image replacement in a table — which contains tabular data, don’t worry — and it was quite loopy. Essentially, it made the table cells 2x the width of the cell above it. I’m guessing there are other situations where this doesn’t work quite right as well, so I I will stick with the proven technique. Fun to learn new tricks all the same, so thanks for sharing!

  134. Building a Responsive Layout With Skeleton: Navigation | Zoombug said on

    [...] Jeffrey Zeldman’s Replacing the -9999px Hack [...]

  135. Building a Responsive Layout With Skeleton: Navigation | cssWOW Showcase | Css Gallery | Css Awards | Design Inspiration Tutorials said on

    [...] Jeffrey Zeldman’s Replacing the -9999px Hack [...]

  136. Jeremy said on

    Awesome technique! Although, I also experienced problems getting it to work on absolutely positioned elements within absolutely positioned containers (in IE & Webkit). The fixis to ensure that the container has a width value set. See here: http://jsfiddle.net/jeremyfrank/rb3kT/

  137. Thierry Koblentz said on

    Fwiw, I wrote something about this technique, I don’t think it’s as good as advertised:


  138. unscriptable said on

    I like this technique!

    Back in 2004, we tried left:-30000px to hide an entire page fragment (not just a bit of text) and found the performance hit to be quite extreme on IE6, but not so much on Firefox. IE6 basically hung.

    We concluded that IE was indeed drawing huge boxes, despite the fact that they were way off screen. Firefox seemed to be entirely unaffected. (We didn’t test in Opera or Safari/KHTML after seeing the IE problem.)

    In conclusion: if you want to ensure that you’re being as efficient as possible in any rendering engine, don’t use huge numbers that may create huge boxes.

    — John

  139. unscriptable said on

    @Matthew Boynes: make sure the element using this technique is inside an element with position:relative.

  140. Marco Berrocal said on

    Two things are extremely interesting

    1) The technique. My question is, browser support?

    2) The -99999px shirt. Where can I get it???

  141. Luiz Marques said on

    Very nice! I had no idea the -9999px way had such a performance problem!

  142. Jason Beck said on

    In addition to some older IE browsers still showing the text, I also find that having any HTML within the container can cause issues – especially something like a line break, or having some kind of header tag or paragraphs. If there’s more than one line, the text wraps… back to the beginning. This despite the white-space declaration.

  143. CSS Image Replacement: 2 nuove tecniche | Edit - Il blog di HTML.it said on

    [...] prima, pubblicata da Jeffrey Zeldmann sul suo blog, non fa uso di text-indent negativo (avete presente ‘text-indent: -9999px’?) e usa [...]

  144. Brian said on

    I used to use -9999px for the h1 tag if its a logo. But now you shouldn’t use it at all.

    You don’t want to hide anything from the user. That is bad SEO. Google will penalize you.

  145. Yubo Zhou said on

    #logo a{
    color: transparent;

  146. Robert Wakeford said on

    Brian. This is still a very valid technique, because whether or not this is bad SEO the reality is that if the client/designer wants it they get it.

    Having said that I’m doing mostly mobile web apps these days, so I’m lucky that I’m able to use @font-face. – hopefully one day we will look back at this as a historic web curiosity much like the i.e. box model hack.


  147. Ray Waldin said on

    This seems like a great, simple image replacement technique, but I’ve found that in WebKit browsers, the replaced text is revealed and highlighted when a cmd-f search matches the replaced text. I’ve posted a minimal demonstration here: http://jsfiddle.net/rwaldin/pf93S/

    Using Safari or Chrome cmd-f search for “search” or “reveal” to see what I mean. You might need to step through the matches with cmd-g a couple times. Anyone ideas how to prevent this?

Comments off.