Back to Home

A new method for replacing text with a picture, or get rid of -9999px

css · html-layout · translations

A new method for replacing text with a picture, or get rid of -9999px

    I would like to talk about techniques for replacing text with an image. I think that almost everyone came across moments in layout, when, for example, you need to use a graphic object for the page title, while keeping the text under it both for search robots and for the print version. And in principle, I never want to break the semantics of the page.



    A little bit about the history of solving this issue.


    The very first popular technique was the so-called FIR (aka Fahrner Image Replacement), which appeared in 2003. It is simple as a stump, and many beginner typesetters still use it:

    Hello world!


    A familiar thing? In fact, inside the tag, in the background of which our picture lies, we add an inline tag that duplicates the text in the picture, and then hide it with display: none;
    Many immediately recognized the curvature of this technique, both in terms of semantics and in terms of weighting html with unnecessary tags. Everything else, it was loved by gray optimizers, as a result of which some search engines applied sanctions to pages overloaded with such objects.

    In the same year , another replacement technique appeared . She worked like this:


    #ID_OF_ELEMENT {
        padding: HEIGHT_OF_IMAGEpx 0 0 0;
        overflow: hidden;
        background-image: url("hello_world.gif");
        background-repeat: no-repeat; 
        height: 0px !important;
        height /**/:HEIGHT_OF_IMAGEpx;
    }

    As you can see, the hack for IE5.5 was used here, in which everything was completely bad with the block model. Subsequently, this technique did not take root, as it stopped working in a number of cases, plus many do not like hacks.

    -9999px


    After all this, the Phark's Accessible Image Replacement technique was born , which is the most popular at the moment and consists of only one line:
    .text-hide {
       text-indent: -9999px (или -999em);
    }

    The technique is not perfect, but if you do not forget about some of the nuances of its work, then it will work for most cases. In particular, check that text-align is directed in the same direction as text-indent (in most cases, text-align: left). And also, do not forget that by applying it to an element with the display: inline-block; property, this element will fly away in IE7 after the hidden text.

    I, like many, was a supporter of "-9999px", but at the same time I understood that this was not the best option and that there should be a more beautiful solution to this problem. Each time, prescribing -9999px, I wondered if these pixels would affect the site in the future.

    New solution


    And so, a few days ago, comrade Zeldman proposed this option:
    .text-hide {
       text-indent: 100%;
       white-space: nowrap;
       overflow: hidden;
    }

    This method solves several problems at once:
    • Firstly, you can be sure that even the longest text that is hidden never reaches the visible container, even if the length of the text exceeds 9999px
    • Secondly, it was first discovered, and then the problem was solved in the same way, which consisted of the following: each time when specifying -9999px, an invisible block of this width was added to the dom tree. And if this had little effect on regular browsers, then on iPad there were serious problems with animation performance ( demo for verification )

    However, this method is also not ideal - if there is padding on the element, then part of the text will look out of it. The problem is solved by zeroing the padding for those blocks where the text is hidden.

    The Zeldman variation revived the leading front-end developers a bit, which lead lively discussions in comments and blogs.
    Also, he was noticed by the html5boilerplate development team, who are now actively discussing on github on the topic of including a new way to hide text in the set of auxiliary classes of their boilerplate.

    In the same thread, another method was proposed that has the right to life:


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

    This method is also cross-browser friendly - tested in IE7-10, Opera 11.61, Chrome 17.0, Firefox 10.0, and Safari 5.1.2. True, for older browsers this option will not work - many of them do not understand the zero value of the font. For example, one of the old Safari can take the value 6 or 8 instead of zero.

    Most of the information about the history and the new method was gathered from this post

    UPD: Another interesting method from Nicholas Gallagher with a pseudo-element , thanks for the tip SelenIT2

    UPD2:In the html5-boilerplate comments on the github, the test results of three IR methods (negative text-indent, positive text-indent and font: 0/0 a) appeared in several screen readers. The option with font: 0/0 a does not rattle in Window-Eyes (as I understand it, it is dying out, it is compared with IE5.5), the rest works everywhere (although with a positive text-indent, the text becomes visible when it is voiced in older versions of JAWS )
    Thanks to SelenIT2 , link to

    UPD3 comment : Chris Coyier did a great job and put together a museum dedicated to Image Replacement techniques: CSS Image Replacement Museum

    Read Next