Clickable Link Backgrounds

Is there any harm in documenting a seemingly rudimentary and obvious CSS technique? I tend to think not, and so the following may (or may not) turn out to be enlightening for you, depending on the level of your CSS-ness.

The Goal

exampleA bulletproof unordered list of links, each with a unique (purely decorative) left-aligned icon that is referenced with CSS — but that is also clickable.

Often I’ll use a background-image on unordered list items to create unique bullets. Applying the background to the <li> element usually gets the job done. But what if our list contains links, where we’d like the image to be clickable as well?

How to Get There

The first step is build the unordered list, adding a unique id to each list item. We’ll use that id to assign each corresponding icon later on.


<ul>
  <li id="email"><a href="/email/">Send an Email</a></li>
  <li id="donate"><a href="/donate/">Donate Money</a></li>
  <li id="active"><a href="/active/">Get Active</a></li>
  <li id="tell"><a href="/tell/">Tell a Friend</a></li>
  <li id="vote"><a href="/vote/">Register to Vote</a></li>
</ul>

Next we’ll add the CSS, which is rather straighforward. Disabling default bullet styling, zero-ing out margins and padding, then assigning a background-image to each <li> element.


ul {
  margin: 0;
  padding: 0;
  list-style: none;
  }
ul li {
  margin: 2px 0 6px 0;
  padding: 0;
  font-weight: bold;
  line-height: 24px; /* height of icon */
  background-repeat: no-repeat;
  background-position: 0 50%;
  }
ul li a {
  padding-left: 30px; /* width of icon + whitespace */
  }
#email { background-image: url(email.gif); }
#donate { background-image: url(donate.gif); }
#tell { background-image: url(tell.gif); }
#active { background-image: url(active.gif); }
#vote { background-image: url(vote.gif); }

So what we’ve done above is given each list item’s link a padding-left that’s at least equal to the width of each icon. This will make the clickable area “stretch” over the icon — which is actually assigned as a background to each individual <li> element.

Also notice the line-height rule. I’ve found this to work out fairly well, matching that value to the height of the icon, so as to show the entire image, and nothing more. This doesn’t seem to negatively affect text resizing issues.

Flicker-free

Why not just assign the image as a background of the <a> element? That’s when we run into flickering problems in IE6/Win. Assigning the image to the <li> element and stretching the link’s width over the image fixes this issue, and thus the main reason for this entire write-up.

You may also be wondering what the harm would be in marking up these images inline with <img> tags. There really isn’t. But the preceding method is another easy way to keep those non-essential images in CSS and out of the markup, making changes to the list and graphics a snap.

There is also a French translation of this article available.