the Future of the Web
  • Home
  • Hire Us
  • Articles
  • About
  • Contact
  • Replace text with an image using CSS

    Nov 8 2006

    Let's say you want to have a logo on a page, but you'd really like to use an <h1> with some text for the header in the HTML. Or maybe you like to use images for all your titles, but would still like to have plain text inside header tags in your HTML.

    There are a number of reasons for wanting to do this, namely accessibility and search engine optimization. I talk more about this in my post Writing Semantic HTML.

    The problem is: How do you hide the text? I think the most popular technique is to wrap the text with a <span> inside the header tag, then use some CSS to 1) hide the text, and 2) use the header tag as an image. Something like this:

    <style type="text/css">
    h1 {
        width: 500px;
        height: 100px;
        background: url(my_header_image.gif);
    }
    
    h1 span {
        display: none;
    }
    </style>
    
    <h1><span>My Great Header</span></h1>
    

    Unfortunately, this technique makes us add an extra tag to our markup, and we all know that every time we use an unnecessary tag, a puppy dies. Either that, or we end up with ugly, unnecessarily bloated HTML.

    Well here's another technique which hides the text just by using CSS. The text will still be readable by screenreaders and search engine spiders, but will disappear like magic for everyone else:

    <style type="text/css">
    h1 {
        width: 500px;
        height: 100px;
        background: url(my_header_image.gif);
        overflow: hidden;
        line-height: 500px;
    }
    </style>
    
    <h1>My Great Header</h1>
    

    This technique works by pushing the text down inside the header with a rather large line-height (it must be at least twice the height). Then the overflow: hidden hides the text since it's overflowing.

    Now isn't that better? No puppies were harmed, and we end up with slightly cleaner and shorter markup.

    Tags: css accessibility
    View 9 Comments | Add a comment
  • Comments

    1. Realazy at 2:44pm on November 8, 2006

    Why not use <code>text-indent: -999em;</code>(any large value), it's more simple.

    2. Jesse Skinner at 3:10pm on November 8, 2006

    Yep, good call. I like that even better. Thanks!

    3. Tom at 2:34am on November 9, 2006

    Personally I prefer a solution with which I can have a virtually limitless amount of text in the <h1> tag - neither of your solutions allow for that.  I tried both using about four paragraphs of text and had problems with both.

    Instead I use the following:

    h1 {
        width: 500px;
        height: 0px;
        background: url(my_header_image.gif);
        padding-top: 100px;
        overflow: hidden;
    }

    4. trovster at 6:21pm on November 20, 2006

    Why would you use height: 0px then a padding-top?

    I prefer the Phark method (text-indent: -9999px; or any arbitrary large negative figure) to the Gilder/Levin image replacement technique (the one mentioned with the extraneous span).

    I don't know why you'd have problems with 'limitless amount of text', but the method below allows for that.

    Personally this is how I do it:

    h1, p.welcome, ul#nav li a {
      display: block;
      overflow: hidden;
      font-size: 0.0; line-height: 0.0;
      text-decoration: none; text-indent: -9999px;
      background: transparent no-repeat 0 0;
    }
    h1 {
      height: 20px; width: 500px;
      background-image: url(header.img);
    }
    p.welcome {
      height: 150px; width: 350px;
      background-image: url(welcome.img);
    }

    This code easily allows for more elements to be replaced. Simply add the selector to the main replacement code, then create a separate declaration with the height, width and path to the appropriate image.

    The display: block allows for the image replacement to be used on inline elements (such as anchors) with no extra code. The 0.0 on font-size and line-height are for bugs in the validator (!). And the overflow: hidden; trims the unsightly long 'focus halo' introduced in Firefox 1.5, so that is only the width of the content.

    5. Jesse Skinner at 8:49am on December 17, 2006

    I've been using Tom's method for some time now and it's really fantastic. It avoids relying on any browser bugs or using arbitrarily large numbers, and just does exactly what you want. Thanks, Tom!

    6. trovster at 12:44pm on December 18, 2006

    Not sure how the method I suggested is relying upon browser bugs. Also, the 'arbitrarily large number' doesn't have to be -9999px;, just the width of the area you're replacing. Because these sizes vary, you use a number which you're unlikely to exceed. You could, infact, use -1024px; if you so wished. As I doubt you're going to replace elements with widths larger than that size.

    7. Bliss at 11:52am on December 27, 2006

    In case, i wish to give hyperlink to the h1?

    8. trovster at 7:54pm on January 24, 2007

    @ Bliss: Then simple use the selector h1 a {} in the code I provided above. The generic code adds display: block, so you can automatically use it on inline elements and it still works...

    9. peter at 6:15am on January 25, 2007

    brilliant!
    i like your solving problem method.

    Add a Comment

    Note: HTML tags and entities will be converted so that they are displayed as you type them. This means if you type in <em>, people will see <em>, and if you type &lt;em&gt;, people will see &lt;em&gt;.

  • Request a Quote

  • Jesse Skinner

    Jesse Skinner
    • Hire Me
    • About Me
    • Email Me
    • RSS Feed RSS Icon
  • Recent Articles

    • Parse Accept-Language to detect a user's language
    • Twitter
    • Three years of The Future of the Web
    • Saving data to a file with PHP
    • Easy web scraping with PHP
    • See all the articles
    • IBM: Where and when to use Ajax
    • Code Igniter 1.6.0 Released
    • Update a Dev Site Automatically with Subversion
    • JavaScript Functions are Variables
    • See All...
  • Categories

    • javascript (37)
    • links (19)
    • about (18)
    • web (14)
    • server (10)
    • html (10)
    • css (8)
    • carnival (7)
    • browsers (7)
    • design (4)
    • seo (4)
    • ads (4)
    • standards (4)
    • events (4)
    • work (4)
  • Older Articles

    • May 2008
    • April 2008
    • February 2008
    • January 2008
    • December 2007
    • November 2007
    • September 2007
    • August 2007
    • July 2007
    • June 2007
    • May 2007
    • April 2007
    • March 2007
    • February 2007
    • January 2007
    • December 2006
    • November 2006
    • October 2006
    • September 2006
    • August 2006
    • July 2006
    • June 2006
    • May 2006
    • April 2006
    • March 2006
    • February 2006
    • January 2006
    • December 2005
    • November 2005
    • October 2005
    • September 2005
    • August 2005
    • April 2005
    • See All...
Copyright © 2008 Jesse Skinner | CSS | XHTML | RSS | Help | Impressum | Cutie Quilts | Internet Blog Top Sites