Embedding decorative foreground images with CSS

Introduction

Shouldn't decorative images (no alt content and/or caption) be inserted with CSS? It's not uncommon to do this, but usually the images are coded as background images with the parent element being sized in CSS. This breaks a useful feature: a user should be able to disable image display, the screen space occupied by the images should then be freed up. Shown here are some methods to embed the images as foreground images by using the CSS2 generated content mechanism via the :before pseudo element. Unfortunately CSS generated content is not supported by IE, but we can feed IE the images as background images and as generated content to browsers that support it.

Examples

Left or right aligned images

Demo using a float:

Paragraph text.

CSS code:

span#float{display:inline-table;float:left;width:152px;height:218px;font:0px/0px serif;background:url(image.png)}
head:first-child+body span#float{width:auto;height:auto}
span#float:before{content:url(image.png)}

HTML code:

<p><span id="float"></span> Paragraph text.<p>

Centered images

A variant that uses a CSS table can be used to center the image.

Demo using a CSS table:

CSS code:

div#css-table{margin:0 0 9px 0;font:0px/0px serif;text-align:center}
div#css-table div{display:table;margin:0 auto}
div#css-table span{display:block}
div#css-table span{display:table-cell;width:152px;height:218px;background:url(image.png) 50% 0% no-repeat}
div#css-table span:before{content:url(image.png)}
head:first-child+body div#css-table span{width:auto;height:auto}

HTML code:

<div id="css-table"><div><span></span></div></div>

Inline images

This requires an inline block element with "shrink to fit" behaviour, this is provided by the CSS 2.0 inline-table or the CSS 2.1 inline-block value for the display property. Unfortunately inline-table is not supported by IE or Gecko based UAs (Mozilla, Firefox, Netscape etc.). MS Internet Explorer first introduced inline-block as a proprietary extension (I don't know when, but it "works" in IE5.5). We are talking about Microsoft, so there is a caveat: IE only applies the value on HTML elements that default to inline, but that suits us fine in this case. Since v7.x Opera also supports inline-block now that it has been incorporated in the CSS 2.1 specification.

You might think "Can't we use the default inline value for the span element?" This is not an option because it's not possible to reliably control the height of the generated inline box containing the image, and since the inline box is anonymous, we cannot attach the needed vertical-align property to the image. The float and CSS table method circumvent this problem by setting the font and line height to nil.

Consequently the following example only works in UAs that support inline-block.

Demo using a inline-block:

Some text, some more text.

CSS code:

span#inline:before{content:url(img/image.png)}
span#inline{display:inline-block;width:55px;height:23px;background:url(img/image.png) no-repeat;font:0px/0px serif}
head:first-child+body span#inline{width:auto;height:auto}

HTML code:

<p>Some text, <span id="inline"></span> some more text.<p/>

What is it good for?

  • Perhaps the principle of using CSS for something which is presentational appeals to you.
  • Or maybe you simply prefer the cleaner and often more structured look of your documents without the presentational images if the document is accessed sans CSS. This can be an issue especially with images floated to the right with CSS, when they end up on the left when the documents is accessed sans CSS the visual structure of a document can suffer.

Footnotes

  • Extensive use of this technique quickly leads to messy CSS due to the hacks needed for IE, and to a lesser extend because most browsers need the :before pseudo selector, maintenance is difficult.
  • Opera 7.x replaces the generated content image with [Image] when image display is switched off, this is rather pointless as in this case the image is strictly decorative so the generation of a replacement text by Opera is inappropriate. In this example an attempt is made to suppress the text by the font:0px/0px serif style rule on the parent element, however, this is unlikely to work as Opera's minimum font size pref setting overrides this (the default setting is 8px). If needs be this can be solved either by setting the display property to inline-table (the float example uses this), or at the expense of inserting extra HTML by setting the span to display:table-cell and enclosing it in a display:table wrapper.
  • It doesn't work in Opera 6 or lower, but the CSS hack used feeds Opera 6 the background image.
  • It has only been tested in Opera 6 & 7, Mozilla 1.5 and IE 5.5
  • CSS borders do not affect the position of adjacent line boxes, thus CSS generated borders could "bleed" into adjacent line boxes. Borders are therefore best applied to the image itself.