Many Apples

More Apples than ever before… what do they mean and where do they come from?

Definitive Solution to Image Replacement

Published 248 days ago

It was a busy day today – a lot of finished projects, so by the end of the day I was pretty tired and started browsing through my archive of CSS experiments, which were mostly done 4 to 5 months ago. Since then I didn’t feel like experimenting… To my surprise I found one little Image Replacement technique I created at that time but didn’t finish. At that time it worked in Safari, and Opera and solution to IE was a little buggy. Well, I finished it and it works for Opera, Firefox, Safari, IE5/Mac, and IE now.

What’s the big deal?

Well, you see, the solution not only works in previously listed browsers; it is also completely semantic and accessible with Images off, CSS on. That all is pretty simple, all I had to change from previous version was a couple of properties. Right now I can only wonder why I didn’t finish it at that time, perhaps because I was unhappy about what happened that day with the Definitive solution to vertical centering with unknown height, but that is not the point. The point is that now I can present this solution to you, my readers.

The idea is fairly simple, use content property for modern browsers and expression for IE, plus implement the old way for IE5/Mac. First of all the HTML code:

  1. <h1>Fecklessmind</h1>

The CSS code that takes care of Safari, Firefox, and Opera is really, really simple:

  1. h1 {
  2. width: 247px;
  3. height: 27px;
  4. line-height: 1em;
  5. white-space: nowrap;
  6. font-size: 100%;
  7. overflow: visible;
  8. }
  9. /* backslash hack to hide some definitions from Mac IE5 \*/
  10.  
  11. #main h1 {overflow: hidden;}
  12.  
  13. /* end of hack */
  14. h1:after {
  15. display: block;
  16. content: url("logo.png");
  17. width: 247px;
  18. height: 27px;
  19. margin-top: -1em;
  20. }

Well, that was easy, right? Now comes the hard part with IE. The thing with IE and expressions is that you can’t properly insert new elements using expressions, luckily this can be overcome by specifying two expressions to perform using , operator, this way everything works as we want it to. (If you want to know more about the problem with expressions and generating new content then e-mail me. I don’t want to go into that here, because it’s not that important.) So here is the first IE bit:

  1. * html h1 {
  2. background-image: expression(this.runtimeStyle.backgroundImage = "none", this.innerHTML += '<span></span>');
  3. position: relative;
  4. z-index: 1;
  5. }

Now the simple and effective IE styling.

  1. * html h1 span {
  2. display: block;
  3. width: 247px;
  4. height: 27px;
  5. background: url(logo.png) no-repeat;
  6. position: absolute;
  7. top: 0;
  8. left: 0;
  9. z-index: 2;
  10. }

Yeah, that’s it and it didn’t even hurt that much, did it? Anyway, you can see it working right here (and if you are lucky enough it has already been implemented on Fecklessmind).

Some final notes

First I would like to say that I know that this write-up is messy, but that’s just the way it is. I hope that it is clear enough though, if not, please, let me know in comments and I will improve it.

And now I should probably name it, so let it be Definitive Image Replacement since it seems to solve most of the issues in a pretty good way. Let me know what you think of it in the comments, any suggestions are highly appreciated. (I also love kind words…)

Alternative styling

Well, not long after releasing this article I came up with alternative styling. This doesn’t mean that what I posted previously is useless, both methods have their uses and, well, the difference is not even noticable.

  1. h1 {
  2. width: 247px;
  3. height: 27px;
  4. font-size: 100%;
  5. position: relative;
  6. z-index: 1;
  7. overflow: visible;
  8. }
  9. /* backslash hack to hide some definitions from Mac IE5 \*/
  10.  
  11. #main h1 {overflow: hidden;}
  12.  
  13. /* well here goes our standards based solution */
  14.  
  15. h1:before, * html h1 span {
  16. display: block;
  17. content: url("logo.png");
  18. width: 247px;
  19. height: 27px;
  20. position: absolute;
  21. top: 0;
  22. left: 0;
  23. z-index: 2;
  24. }
  25.  
  26. /* some of the styling for stupid Windows IE */
  27.  
  28. * html #main h1 {
  29. background-image: expression(this.runtimeStyle.backgroundImage = "none", this.innerHTML += '<span></span>');
  30. }
  31. * html h1 span {
  32. background: url(logo.png) no-repeat;
  33. }
  34. Download this code: /code/css/code-001.txt

You can see it working right here. Sadly, this second example doesn’t work in Firefox with images OFF, otherwise just fine. Therefore I recommend using the first solution. I will post later today about how to style multiple headings with different styles and not to get a big file-size. Don’t be fooled by the looks, this solution doesn’t take as much space as it seems to.

Update: There is now description of DIR usage available.

2. Update: Yuhů notified me that the Expression was generating two SPANs in IE; which is, of course, wrong. He also supplied a solution to this problem in form of switching the two parametrs, for which I thank him a lot. All the example sources to this article have been corrected.

3. Update: A lot of updates, eh? Well, Jason Davis pointed out that he already had a similar idea one and a half year ago, using the same expression. His main styling is different, but the IE part of the solution is the same as mine. He called his version GIR. Go see it, it even has the Opera bug solved – even though the hack used is not very reliable one (or at least that’s what I think) and I wouldn’t recommend using it (the hack).

Read the comments

Feel free to comment and read comments, but remember to relax and be polite - whatever people say, it's not the end of the world.

  1. Oswald speaks:

    Nice idea!

    But Opera (I test 8 Bet3 and 7.5 final) when images are off, it shows instead of the image a default text for missing image.

    Here is a screenshot:
    http://www.webkitchen.cz/tmp/fecklessmind-ir.gif

    Posted 248 days ago [#]

  2. Anatoly Papirovsky speaks:

    Yeah, thanks, I saw that... Sadly that is one of quite stupid behaviors of Opera and there is not much I can do about it. It doesn't degrade the quality of the solution though. ;) It still works better than anything we had so far...

    Posted 248 days ago [#]

  3. Jeff Hickman speaks:

    Really nice work!

    Posted 247 days ago [#]

  4. Kristopher speaks:

    Thanks for the example. It deffinately went under my "Reference" bookmark list. Since I'm just a novice (not really a noob, but not a pro), I have 3 questions that it'd be sweet if you could reply to:

    1. What did the line-hieght/negative em top margin do exactly?
    2. Was the purpose of the "text-indent: -500em" just to get the text out of the way?
    3. What was the purpose of the * in front of "html h1" in your IE hacks?

    Great write up!

    Posted 247 days ago [#]

  5. Anatoly Papirovsky speaks:

    Kristopher: Absolutely no problem with answering your question, I am even glad that you asked... :)

    1. The line-height and negative margin-top in the first example are set in order to put the generated image over the text and keep it there even when the text is resized.
    2. That wasn't supposed to be there, or at least not in the way it was presented. Sorry... (that was just if you wanted IE5 to show image, and I forgot the second rule - look at the source again to see the correct version)
    3. The * in front of html h1 is a hack for Internet Explorer - you are selecting html out of all tags, but there is no other element nesting the html therefore there is nowhere to select it from; IE doesn't understand that and applies the rule, other browsers don't.

    The point of the article was to show a better alternative to all the Image Replacement methods out there, this one focuses on both semantics AND "images off, CSS on" scenario.

    Posted 247 days ago [#]

  6. XThom speaks:

    Well, nice idea, but I think this code is a little bit easier:
    CSS:

    #header { // tag div
    ..
    background:url(logo.png);
    ..
    }
    h1 {
    display:none;
    }

    Isn’t it?

    Posted 247 days ago [#]

  7. Anatoly Papirovsky speaks:

    XThom: First of all, your idea doesn't work with images off, CSS on; second, screenreaders, search-bots etc. won't be able to read that content; and third, you are using extra unnecessary mark-up.

    Right now this solution is the closest you can get to perfect, I believe.

    Posted 247 days ago [#]

  8. Filosof speaks:

    Tož to už stojí za implementaci :-)

    (Editor's Note: Please keep all the comments in English (even though I speak Czech). I won't delete comments in other languages, but I'm not too happy about them. If you must, then at least provide English summary. Thanks.)

    Posted 247 days ago [#]

  9. pixy speaks:

    I’m affraid, in Safari it doesn’t work well, too. See this http://www.pixy.cz/pixylophone/obrazky/fecklessmind.png

    Maybe, it would be better to use longer replaced text to see if it’s correctly cut and if the overflow:hidden really works (I had to grow up the font size).

    Posted 247 days ago [#]

  10. Anatoly Papirovsky speaks:

    Pixy, I use Safari also and it indeed doesn't work but not because the solution is bad, it is simply my mistake I took out the overflow: hidden; for some testing and forgot to put it back in. :( I will correct it...

    In fact, Safari and IE are the only browsers which support this without any problems, even small ones. The problem with Firefox is that I couldn't disable images, it seems to always leave them... :-/ Opera was discussed earlier. But these are really minor problems compared to advantages.

    Posted 247 days ago [#]

  11. matt keogh speaks:

    Good solution but not definitive in my opinion as it’s a shame the CSS doesn’t validate.

    Posted 247 days ago [#]

  12. !..:::digital.j3sus:::..! speaks:

    Nice work , man!

    Posted 247 days ago [#]

  13. habendorf speaks:

    Without :after, without expression:
    http://diskuse.jakpsatweb.cz/index.php?action=vthread&topic=4066&forum=7&page=-1

    on view: www.brs.cz/new

    Posted 247 days ago [#]

  14. Anatoly Papirovsky speaks:

    habendorf – Your solution has many drawbacks to it and is in no way new. Please, don’t post unless you understand the article. Or at least ask questions. There is reason why this is better and it’s written all over the place here! It doesn’t use any extra mark-up and it works in “images off, CSS on” scenario – last time I say it.

    Posted 247 days ago [#]

  15. Rob Mientjes speaks:

    :) It indeed works quite well. But alas, some people don’t get it. Do read the explanation before commenting with your own method…

    Posted 247 days ago [#]

  16. Scott speaks:

    Just stumped across this and wow, looks good.

    Posted 247 days ago [#]

  17. ever.cz speaks:

    hey man,
    it’s really good! congratulation! thank you!

    Posted 247 days ago [#]

  18. Jason Davis speaks:

    I wrote about nearly exactly the same thing a year and four months ago:
    http://www.jasonkarldavis.com/articles/gir/

    I called it GIR and the expression-technique the “one-time-use expression”.

    Posted 244 days ago [#]

  19. Anatoly Papirovsky speaks:

    Jason as I said on Accessify I haven’t seen your technique previously… :-/ But it seems to be different in some things, though I can always credit you for it… after all one and a half year, well, I’m a bit late I guess. :D Could you e-mail me, please?

    Posted 244 days ago [#]

  20. Justin Perkins speaks:

    Anatoly-
    Download the Web Developer Extension:
    http://chrispederick.com/work/firefox/webdeveloper/

    You can turn images off, CSS off, Javascript off, animated GIFs off, etc… all within one simple menu. It’s the best. I tested in Firefox and it worked great.
    Images On/CSS On: Good
    Images Off/CSS On: Good
    Images On/CSS On/Javascript Off: Good

    Posted 244 days ago [#]

  21. Anatoly Papirovsky speaks:

    Justin: There is some weird bug in Mac Firefox which stops it from turning off images… It just doesn’t work. :( But I, of course, have the webdev extension. ;)

    Posted 244 days ago [#]

  22. Justin Perkins speaks:

    You may want to upgrade the extension, if you’re not up to the 0.9.3 yet. It changed a little bit and may work for you. I’m going to test on my Mac when I get home and see if I can get Firefox to behave ;)

    Posted 244 days ago [#]

  23. Andy speaks:

    Nice solution, I will definitely play around with it! Have you seen this one?

    http://wdhaven.com/article/12/bir

    Posted 244 days ago [#]

  24. Anatoly Papirovsky speaks:

    Yeah, Andy, I think I’ve been there (through link in Malarkey’s comments, I believe)... :)

    Posted 244 days ago [#]

  25. dave speaks:

    nice method.
    I thought I’d try and tweak it so the standards clients could use a transparent image without the text showing through. Generating the image before pushes the text out of the box,but as I cant switch images of either in firefox, I cant tell what happens.I made the generated image inline and no dimensions, but it kinda works – how do you turn images of on a mac…?

    also my old (pre panther) safari insists on centering the h1 – which seems so silly I can’t even be bothered to look at it, any ideas about that? I know i’m lazy but it is 4.00 am here :)

    Posted 244 days ago [#]

  26. dave speaks:

    if you turn of images in firefox and reload on my mac the images are still visible, but loading the url in a new window or tab shows the page without the bg images, and the txt as expected :)

    Posted 244 days ago [#]

  27. Matt Wilcox speaks:

    Nice write up, and an interesting idea. The only problem I can see is that the replacement image must be larger than the original text, or you will see text popping out from under the image. That might be fixable by changing the overflow property however. I’ve yet to test it. :-)

    Posted 244 days ago [#]

  28. Anatoly Papirovsky speaks:

    Overflow is set to hidden in both examples I believe… :) Even if not it is written in the article itself.

    Posted 244 days ago [#]

  29. juan carlos speaks:

    Nice, but not fully accessible. While this may work for screen readers, you of course cannot resize the image when you have both CSS and Images on! This is the general issue of using text in images. For the simplest of things you could define your image dimensions in ems so it will resize, but of course it may still be difficult to read.

    In my opinion, it would be better to stick with normal text, though you of course loose some nice typography…

    Posted 244 days ago [#]

  30. adam speaks:

    This is one of the nicest solutions I’ve seen yet. Great work! :-)

    Posted 244 days ago [#]

  31. medyk speaks:

    yeah… I wrote a lot.. didn’t fill email field and after reminding page I lost everything I wrote.. ah.. you better fix that..

    Posted 244 days ago [#]

  32. Cedric Francois speaks:

    This is brilliant! Much better than anything I’ve tried so far. Cheers!

    Posted 244 days ago [#]

  33. Mike speaks:

    I have always strayed away from expressions, but this might be too good to pass up. As much as people have ignored the style-on, images-off scenario, I think it’s still vastly important to accomodate those users (esp. here in the US where many developers tend to forget about dial up people).

    Posted 243 days ago [#]

  34. James Archer speaks:

    I’m not sure how close it is (I haven’t looked it over too carefully yet), but this method I just stumbled while looking for something else across reminds me a lot of DIR:

    http://www.sitepoint.com/print/header-images-css-xhtml

    Posted 243 days ago [#]

  35. Trench speaks:

    Anatoly, just an observation here… but chill. I don’t say that mean-spirited, or with ill-intent, rather I say it like Arsenio might have said it to Hammer when the need arose. Chill. ;)

    I’m picking up a lot of very defensive jabs in your comments both here and 456 berea street, and I’m sure other readers are as well. It’s not helping your cause. Sure, you have every right to defend your work, but me thinks a better alternative would be to present your work to the world and let it stand on its own.

    Also, when naming a project, try to stray away from words like “Definitive” as a title, because that’s only begging for endless rebuttal (such as you’ve been getting).

    For me, I say congrats for trying to find solutions, and presenting them for others to consume.

    For others, lay off the incessant rebuttals… it’s about as annoying as a rape whistle. Not that I’ve, um, heard one. :)

    Posted 242 days ago [#]

  36. Anatoly Papirovsky speaks:

    Trench – Hmm, I think you missunderstood my comments or something, as there is only one defensive comment which was on 456 Berea street (the second comment) which was explained. Otherwise I am mostly joking, or cursing at myself… or happily explaining something. You should often look at the smilies I use, that will help you understand me… And, well, there are two comments here on other presented solutions which may sound a little rude, but that’s just because people don’t read – if you don’t read that’s what you get. I’m sorry, but that’s the way it’s gonna be – if they don’t bother being nice, I certainly won’t.

    Anyway, thanks for your input. ;)

    Posted 242 days ago [#]

  37. Trench speaks:

    Yesterday I had a bit of Xanax(Definitive Chill Solution) in my system, so everybody seemed a bit more tightly wound than myself. :) Apologies.

    Posted 242 days ago [#]

  38. john speaks:

    Unfortunately, this method will not work if the user is browsing around with javascript turned off.

    Posted 238 days ago [#]

  39. Anatoly Papirovsky speaks:

    john – Mistake, mistake… expressions work even with JS off, depends on your security settings. There are very few people who play around with Security settings in IE… ;)

    Posted 238 days ago [#]

  40. Klaus Hartl speaks:

    Hello Anatoly,

    first of all, good job! I have a question about that dynamic properties and security settings: Which security settings will keep these expressions alive? With standard settings on they won’t work here if I then turn off scripting.

    By the way, I thought a long a time these expressions cannot be turned off at all, because I read it on the reference at MSDN, but that was related to some IE 5 beta version. As you said it before, one should always read thoroughly :-)

    Posted 235 days ago [#]

  41. Anatoly Papirovsky speaks:

    Klaus, I don’t know… it works on mine with security settings to standard… :D I guess IE can’t even behave the same way on two different computers with the same settings. :-/

    Best regards,

    Anatoly

    Posted 235 days ago [#]

  42. Jens Meiert speaks:

    (Pow, my first comment apparently has been removed.)

    From my point of view, DIR still is to be considered harmful since it uses invalid CSS. Taking such no-nos into account, the most economic alternative is the Phark method, the most flexible is SIIR. My article on IR techniques (German) gives a comprehensive overview.

    Posted 190 days ago [#]

  43. Jon speaks:

    I know this is a little late in commenting, but I’ve been greatly benefiting from the IR technique you have here.

    That said, I’m trying to work out a rather special situation. First, I’ve been using hover states for links that use images instead of the text itself, utilizing :after:hover. It’s fine if you try to replace one image with another image in another separate image file, but I’m trying to use the “two pics in one image” technique (hover and regular states in the same image), move the picture down for the hover state.

    Using something like “margin-top: -3.5em;” or “margin-top: -56px;” (relative to the image size), it works if you keep the font size at the regular level. But if you try to make the text larger or smaller, like say in Firefox “View > Text Size > Increase” it throws off the hover states. The normal state is of course alright, but somehow the image position is fixed to how big the text size is.

    Would anyone know how to fix this so that the hover state picture doesn’t get affected by font size?

    Posted 69 days ago [#]

  44. Gabriel Porras speaks:

    In this article the examples:
    • http://fecklessmind.com/clients/css/ir/index-alt.html
    • http://fecklessmind.com/clients/css/ir/
    Have a probblem: the link (a atribute) dont´work in IE6.
    Also the examples in the article “Description of DIR usage available” preseten 404 errors.

    Posted 21 days ago [#]

  45. jay speaks:

    image replacement makes my head hurt.

    thanks for the solution.

    Posted 20 days ago [#]

  46. order tamiflu speaks:

    great work guys, keep it up

    Posted 18 days ago [#]

Add your [feckless] comment





Remember


Live comment preview is enabled (plus Live Gravatar).
Textile is enabled, (X)HTML will be stripped.
If you are using Safari, Firefox, Mozilla or Internet Explorer your post should be submitted live so there will be no reloading.

Gravatar

speaks: