tags:

views:

45

answers:

2

I'm trying to replace <img> elements with emoticons with different images through CSS (so that I can match them to the style being used). I thought that I can just insert another smiley with the :before CSS pseudo-element, and hide the original element. This would work, except that the browsers don't seem to insert the extra image! This only happens if I try it with an <img> element, works perfectly when I try it with <span>. The code I tried:

<!doctype html>
<style>
img.icon:before {
    display: inline-block;
    content: url(smiley.png);
    width: 16px;
    height: 16px;
}
</style>
<p>Lorem ipsum <img src="smiley.png" class="icon" alt=":)"> dolor sit amet...</p>

The specification at http://www.w3.org/TR/CSS2/generate.html#before-after-content has a note at the bottom:

Note. This specification does not fully define the interaction of :before and :after with replaced elements (such as IMG in HTML). This will be defined in more detail in a future specification.

We are using a background image, like it is suggested in the comments, but that has the problem that the images won't print with default printing settings then. The next option we are considering is using <span class="icon"><img ...></span> and putting the :before on the span, but it's a little ugly.

I also wonder if this is specified in CSS3 so that there is a chance for fixing it in the near future.

A: 

It's almost certainly easier to use:

img.icon:before {
display: inline-block;
background-image: transparent url(smiley.png) 0 0 no-repeat;
width: 16px;
height: 16px;
}

You might not want to use background-image, but the :before and :after psuedo-elements are already poorly implemented; trying to use content to place images is probably a step too far at this stage.

I'm not sure I see the point of this approach, though; it seems you'll end with two versions of smiley.png next to each other. This might be more easily implemented (replacing the generic smiley.png with a themed smiley.png) on the server-side, than client.

David Thomas
The problem with background is that it won't print by default.Replacing the image is not an option, because this is supposed to work with user-selected alternate stylesheets -- different styles need different icons.
Radomir Dopieralski
A: 

Another way to do this is just set a background-image and hide the img element with overflow, without using :before:

<style>
.icon { 
  width: 0;
  height: 0;
  padding-top: 16px;
  padding-left: 16px;
  overflow: hidden;
  background-position: 0 0;
  background-repeat: no-repeat;
}
.smiley { background-image: url(smiley.png); }
</style>

<img class="icon smiley" src="smiley.png" alt=":)">

Also, have a look at this article about using data attributes instead of classes for this.

Andrew Vit
We tried that, but this has the problem that the images won't print with default browser settings.
Radomir Dopieralski
What about scoping it to a `@media screen` vs `@media print` block?
Andrew Vit