Search and Contact

e-mail:
adipalaz@yahoo.com

writings

Inline links with background images - three simple fixes for IE

December 3, 2007

Internet Explorer renders the positioning of the background-image on inline links differently, compared to other browsers, when the links are split over two lines. The background image may disappear, or may be displayed at the end of the first line, overlapping the text. Here you will find three simple CSS solutions. The proposed approach is illustrated using as an example inline external links with background icon.

Introduction

Applying a small background image to a link, indicating that the user will be taken to an external site, is an option that enhances usability and accessibility.

The method used here to accomplish this is the following: the external links have class="external"; since I have already my common links styled, I’ve appended these rules to the main CSS file:

CSS:

a.external:link, a.external:visited { background:transparent url(../img/ext_link.gif) no-repeat 99% 5px; padding-right:15px; }

a.external:hover, a.external:active { background:#fcfcfc url(../img/ext_link.gif) no-repeat 99% -145px; padding-right:15px; }

NB: A background icon can be automatically applied to all external links using the CSS 3 attribute selectors[1]. Remember that they are not supported by IE6. (Update: Sorry to say, but IE6 is still among the most common browsers – according to W3Schools, in April 2008 the usage share of IE6 (external link) was 28.9%.)

Here is a small example with a list of links styled as "external" with the above CSS declarations:
(the links in all examples below are empty, don’t trouble to click them)

Although this technique is widely used in various web sites, many of them show an annoying "bug" in different versions of Internet Explorer.

The problem

Inspect the example of inline links inside a long text to see the inconvenient IE behaviour:

Example:

Let's keep smiling, let's keep laughing, let's be happy! Let's keep smiling, let's keep laughing, let's be happy! Let's keep smiling (internal link), let's keep laughing, let's be happy! Ho-ho-ho-ho- HA!

At first sight everything may seem to work correctly. But if you have IE installed, play a bit with the browser window horizontal size and see what happens if the link text, consisting of 2 or more words, wraps over two lines. The background image is displayed at the end of the first line, overlapping the text. In some cases, depending on the background icon position, it may disappear.

For those who don’t use IE, here is a screen shot illustrating the problem:

Current state of the used workarounds

The workarounds I’ve found use an un-semantic and redundant HTML code. They include 1.) an empty <span> on which the background is set; 2.) the last word of the link text is wrapped in a <span> and the background image is set on it; 3.) a <img> is inserted inside the link in the HTML code either statically or dynamically via scripts[2]; some sites use :before or :after pseudo-elements to insert the images[3]; the pseudo-elements can be used in combination with the CSS 3 attribute selectors[4] - IE doesn't support the last two techniques; 4.) in some sites the background images are hidden for IE.

As I prefer something more elegant and simple, I’ve tried to find a fix by myself.

Workarounds:

1. white-space: nowrap;

My first attempt was to avoid the words in links to overrun, by wrapping the examples in a paragraph with class="nowr", declaring only for Internet Explorer:

CSS:

.nowr a.external { white-space:nowrap; }

Result:

Let's keep smiling, let's keep laughing, let's be happy! Let's keep smiling, let's keep laughing, let's be happy! Let's keep smiling (internal link), let's keep laughing, let's be happy! Ho-ho-ho-ho-HA!

This simple declaration works for IE5.5. But if the link text starts at the beginning of the line, IE6 and IE7 don’t show the background image. See the screen shot:

Some web sites display this "bug" although there is a simple workaround witch I have discovered: relative position of the link fixes the problem in IE6 and IE7. But even though the background icon appears in the right place in IE6, in some cases it may look broken:

CSS:

.nowr a.external { white-space:nowrap; position:relative; }

Result:

Let's keep smiling, let's keep laughing, let's be happy! Let's keep smiling, let's keep laughing, let's be happy! Let's keep smiling (internal link), let's keep laughing, let's be happy! Ho-ho-ho-ho-HA!

2. display: inline-block;

I have played a bit with the CSS and came up with another solution: to make the external link to behave as inline-block using the CSS display:inline-block declaration (see IE7-/Win: inline-block and hasLayout (external link) for explanation). After applying it, it rests to adjust the line-height, the margins, the position, and the vertical-align of the inline-block link. That's all. But don't forget to address it only to Internet Explorer.

This time, the container of the examples with external links has class="inlineblock".

I addressed the following rules only to IE:

CSS:

.inlineblock a.external:link, .inlineblock a.external:visited { display:inline-block; line-height:1.3em; margin:0 0 0.3em; vertical-align:middle; position:relative; top:0.15em;
background:transparent url(../img/ext_link.gif) no-repeat 99% 5px; }

.inlineblock a.external:hover, .inlineblock a.external:active { background-position:99% -145px; }

You can see the result below:

Result:

Let's keep smiling, let's keep laughing, let's be happy! Let's keep smiling, let's keep laughing, let's be happy! Let's keep smiling (internal link), let's keep laughing, let's be happy! Ho-ho-ho-ho-HA!

3. Adding descriptive text, wrapped in a <span>, to the external links and setting the background image on that <span>

Applying background images doesn't help users of non CSS supporting browsers. As Russ Weakley proposes in his article: Simple, accessible external links (external link), it is a good idea to add descriptive text to all external links, and then replace this text with a small icon.

"...every external link should be identified within the link text itself. For example, you could use " (off-site link)" or "(external link)" within any link text that points to any external resource."

Russ Weakley

The IE misbehaviour is mentioned in the article without giving a solution, but as you can see below, it can be easily fixed by setting the background image not on the link itselve but on the <span> wrapping the descriptive text.

HTML:

<p class="span"><a class="external" href="#nowhere">keep laughing<span> (external link)</span></a></p>

I've appended this rule to the main CSS file:

CSS:

a.external span { position:absolute; text-indent:-9999px; }

I addressed the following declarations only to IE (I think that these rules don't endanger any browser and, if you want, you can add them to the main CSS file):

CSS:

.span a.external:link, .span a.external:visited { background-image:none; }

.span a.external:link span, .span a.external:visited span { background:transparent url(../img/ext_link.gif) no-repeat 99% 5px; }

.span a.external:hover span, .span a.external:active span { background:transparent url(../img/ext_link.gif) no-repeat 99% -145px; }

Result:

Let's keep smiling (external link), let's keep laughing, let's be happy (external link)! Let's keep smiling, let's keep laughing (external link), let's be happy! Let's keep smiling (internal link), let's keep laughing (external link), let's be happy! Ho-ho-ho-ho-HA (external link)!

This method has two benefits - the accessibility is enhanced and, in addition, we have a semantic holder for our external links background icon.

Update: The Ingo Chao's article Background images lost on multi line inline links (external link) contains interesting information about the same problem. I thank Ingo for pointing me out that the word bug is not the right term for this inconvenient IE behaviour, because "The tiling and positioning of the background-image on inline elements is undefined in this specification" (CSS 2.1:14.2.1) (external link)

Please let me know what you think about the proposed here solutions, especially if you have found a better workaround to solve this problem.


Recent writings