Blog

Right Aligned CSS Background Images / IE Word Wrap Bug

I recently built a design that called for various navigation elements to have bullets aligned to the right of each link. It seemed simple enough but turned out to be harder than I’d imagined.

I started with the following CSS:

ul.bulletsOnRight { padding: 0 0 10px 0; list-style-type: none; }
ul.bulletsOnRight li { padding: 0 0 6px 10px; background-image: none; }
ul.bulletsOnRight li a { color: blue; text-decoration: none; padding: 0 10px 0 0; background: url(images/bullet.gif) 100% 50% no-repeat; }

This code works in most situations except for one major one. In Internet Explorer, when an item wrapped to more than one line, the bullet shows up in the wrong place, or sometimes not at all. The image below shows what was happening.

Bullet Demo

It would appear that IE doesn’t know how to handle the background-position when the element wraps to multiple lines. The easy way to fix it is to apply the bullet to the last WORD in the element instead of the element itself. We can do this by wrapping the word in a span tag like so:

  • Test bullet that is long enough to wrap to two lines
  • We then move the background image and associated right padding to the span element.

    ul.bulletsOnRight li a { text-decoration: none; color: blue; }
    ul.bulletsOnRight li a span { padding: 0 10px 0 0; background: url(images/bullet.gif) 100% 50% no-repeat; display: inline-block; }

    Note that the display: inline-block; element is needed to trigger hasLayout in IE6.

    Problem solved… sort of. This technique works great, but it does require you to add an extra element to each item in your navigation which could be problematic for large sites or sites that are managed via a CMS. So let’s remove that span tag and add it in when the page loads via a bit of jQuery.

    $(document).ready(function() {
         $("ul.bulletsOnRight li a").each(function (i) {
              // Get the text of each link and trim any whitespace
              var contents = jQuery.trim($(this).html());
              // Split into an array
              var a = contents.split(/\s/);
              // Wrap the last word in a span tag
              a[a.length - 1] = "" + a[a.length - 1] + "";
              // Join the array back together and update the html text of the link
              $(this).html(a.join(" "));
         });
    });

    This is a great example of using JavaScript for progressive enhancement of a page. While most users will see our list with bullets as intended, those without JavaScript will still see an easily-usable list so little is lost if the JavaScript is absent.

    See a demo of this code in action.

    Leave a Comment