How to Create a Block Hover Effect for a List of Links

Among the many things to like about Veerle’s redesign of her blog is the way she does the hover effects for lists of links, such as those in her “approved” section.

Rather than force others to wade through Veerle’s CSS (wow, that’s quite a stylesheet!) I thought it’d be helpful to show how to create this “block hover” effect.

Link hover effect on Veerle’s blog

The Example

First, view my link hover effect example and roll over the list items to see the block hover effect in action.

The Code

The HTML is quite straightforward. Because IE only supports the :hover element for links, the link anchor needs to go around all the text in the list item.

Therefore, we need to provide some additional hooks in order to style the content. We do this through the use of<em> and <span> tags.

&lt;div id="links"&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a title="Text" href="#"&gt;Link Heading One
&lt;em&gt;Description of link.&lt;/em&gt;
Date posted&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a title="Text" href="#"&gt;Link Heading One
&lt;em&gt;Description of link.&lt;/em&gt;
Date posted&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;

And now the CSS. In order for the block hover effect to work properly in IE, we need to make the width of the link the same as that of the list item.

Otherwise the hover effect will only display when you mouse over the text within the list item.

#links ul {
list-style-type: none;
width: 400px;
}
#links li {
border: 1px dotted #999;
border-width: 1px 0;
margin: 5px 0;
}
#links li a {
color: #990000;
display: block;
font: bold 120% Arial, Helvetica, sans-serif;
padding: 5px;
text-decoration: none;
}
* html #links li a { /* make hover effect work in IE */
width: 400px;
}
#links li a:hover {
background: #ffffcc;
}
#links a em {
color: #333;
display: block;
font: normal 85% Verdana, Helvetica, sans-serif;
line-height: 125%;
}
#links a span {
color: #125F15;
font: normal 70% Verdana, Helvetica, sans-serif;
line-height: 150%;
}

It’s not necessarily the most semantic markup in the world, especially with those <span> tags, but I’m not sure how else you’d do it. If anyone knows of a more semantic method, please let me know.

Further Reading

33 thoughts to “How to Create a Block Hover Effect for a List of Links”

  1. Yay! I had been curious how she did that. It looks good. Now if I could figure out how to get here design skills. *sigh*. Thank You!

  2. It’s worth noting that you surround the entire list item in a link tag because IE only handles the :hover element on link tags. Ideally you would be able to assign the :hover to #link li. But in the interest on making sure it works for everyone you use the link tag.

  3. Slight improvement : add width:400px; to the #links li a declaration so that the whole block actually behaves like a block, i.e. the hover effect occurs even if you hover the block, not just the link text within it, on MSIE.

  4. Michael – good point. I’ve updated the post to mention this.
    Ozh – good catch! I actually needed to apply the width to IE only using a hack because I’m using padding to indent the link within the list item.
    If I just add width:400px to #links li a the link would be wider than the list item in Firefox (i.e. 400px + 10px of padding).

  5. You may want to consider using IE conditional comments if you are applying specific rules for IE. We used a similar “width” rule on a recent navigation list and put this into a separate style “IE only” sheet that is called by the IE conditional comment.

  6. Clive – good point, especially with IE7 on the horizon. I deliberately used the straightforward * html hack with the intention that others can apply their preferred IE hack on their own sites.
    I do agree that, going forward, conditional comments are probably the best way to deal with IE hacks.

  7. This is a cool technique. As for cleaning up the code, I would consider replacing the em with another span, and giving the spans meaningful class names like “description” and “postdate”. Adding emphasis to link descriptions doesn’t make much sense, and doesn’t add much semantic value. You usually don’t tell someone the address of a building, and then burst into an excited speech describing it. This situation is similar.
    On the other hand, the adding emphasis to the description might help add variety for those using a screen reader, or those viewing the unstyled page. In that way, the em may be useful. Therefore, I’d keep the em but add a meaningful class name.
    The line breaks can probably be safely removed, if you set the spans (and em, if you keep it) to display block. This doesn’t break css html validation, and works in the browsers I’ve tried. You’re not supposed to have block-level elements within an anchor tag, but since the anchor is also block-level in this case, the span is considered inline for validation purposes, and it works in visual browsers, I’d say it’s safe. Brending this guideline doesn’t upset the validator, and it doesn’t adversely effect content delivery in my experience.

  8. Scott – thanks for the great tip! I removed the <br /> tags and used display: block; for the <em> tags. Much better!
    On another note, I would suggest that your application of the <em> tag seems a little narrow to me.
    The W3C simply says that EM ‘indicates emphasis’. And one of several “definitions of emphasis”:http://www.answers.com/emphasis&r=67 is ‘special weight placed upon something considered important’.
    I would say that a description of something could definitely be construed as being worthy of giving emphasis.
    I think that <em> is rather more versatile than we give it credit for; much like the often misunderstood “definition list”:http://www.w3.org/TR/REC-html40/struct/lists.html#h-10.3 – did you know that the W3C suggest it be used to mark up a dialogue between speakers?!

  9. You don’t need to add the actual width (400px or whatever it may be) to the IE rule; it just needs any width for the “display: block;” to work properly (a hasLayout bug).
    The simplest way to do this is to use:
    * html ul li a { width: 1%;}
    That way you’ve not tied the width of the links into that particular rule in your stylesheet.
    See here for a more detailed explanation and examples. 🙂

  10. this is very similar to the techniques used when creating drop down menus
    I suggest not messing up the html and instead using the .htc file created by Peter Nederlof
    * Peterned – http://www.xs4all.nl/~peterned/
    this allows :hover to be applied to all the html tags in IE and will give the desired effect much more efficiently

  11. good stuff, I looking for this a long time, its so simple 😀 but my config won’t work ^^

  12. Of course, you could just apply the :hover pseudo-element to the li tag and forget the losers still using IE6, but I guess that would be kind of mean.
    This technique is ‘behavior’ more than ‘presentation,’ so why not jsut write a simple javascript function? That way you can get rid of the non-semantic mark-up and have it work on any browser.

  13. save this code as hover.htc
    [attach event=”onmouseover” handler=”hoverRollOver” /]
    [attach event=”onmouseout” handler=”hoverRollOff” /]
    [script type=”text/javascript”]
    function hoverRollOver() {
    // backup origonal className
    element.origClassName = element.className;
    var tempClassStr = element.className;
    tempClassStr += “Hover”;
    tempClassStr = tempClassStr.replace(/s/g,”Hover “);
    tempClassStr += ” hover”;
    element.className = element.className + ” ” + tempClassStr;
    }
    function hoverRollOff() {
    element.className = element.origClassName;
    }
    [/script]
    I don’t remember where I got this behavior but I believe it isn’t the same as peters. If I recall his requires the page to be loaded before it applies the classes.. this one does it once the dom is ready and before the page has finished loading binary data (I believe.)
    Include it like so in the css…
    ul#id li {
    behavior: url(‘hover.htc’);
    }
    then on the li:hover duplicate the selector as li.hover.
    i.e.
    ul#id li:hover, ul#id li.hover {
    rules;
    }
    and you have hoverable li in ie. Make sure your server send the right mime types on htc files and that the include path in the css is relative to the document not the css file.
    I take no credit for any of this except my efforts to spread the word.

  14. Just a note.. this allows you to have multiple useable links in your hoverable li.
    The link on the date could go to an archive for that date, the link on the header and teaser could go to the article and you could add the author name and link to an archive of that authors posts. This allows your list to be more functional and your users to have more options.

  15. Nice solution. I used JavaScript to apply the link to the entire block element, if block elements are required within the clickable area. Not an ideal solution, but it is simply adding usability while not detracting accessibility so I think a JavaScript solution is appropriate in the block-required scenario.
    I prefer your emphisis solution compared to Veerle’s line-break markup. Well-done.

  16. Genial. Estupendo artículo. No se si se pued escribir mejor el marcado, pero el caso es que sirve a la perfección. Mil gracias.
    Salu2.
    Enrique

  17. Forget jumping through all the css hoops to make the whole block hover on rollover. Just use the hover.htc file. Include it in the main directory and include it on the in your ie.css file which should be linked to with a conditional comment.
    http://www.xs4all.nl/~peterned/csshover.html
    Then just add something like li:hover { background: #EEE; }

  18. *squeg* – you can certainly look at Veerle’s CSS file.
    However, I thought it might be useful to pull out this example, especially for people who are less familiar with CSS (her CSS file is pretty complex).
    Also, I think it’s become apparent from the discussion that there are other ways to achieve this effect, which benefits us all.

  19. It’s a pretty good example, but as with many other, it has some flaws.
    I would use a different approach, since the block contains several degreedes of structure (headline, paragraph etc.).
    The DOM-markup can be like your example, but the source markup should be marked up with its respective H- and P-elements.

  20. I really like the look of this technique. Do you guys know what is the easiest way of not having the space underneath each li ?
    I would prefer to have it look like the Veerle site – where the bottom dotted line is the top of the new li.

  21. *Adam* – you just need to remove the top and bottom margin from each <li> and only apply a bottom border to each rather than the top and bottom border as I have done in the example.
    Without testing it, I think your CSS would be:
    #links li {
    border-bottom: 1px dotted #999;
    margin: 0;
    }

  22. i had posted a very similar article to this at my own site not too long ago (about a month prior), except the method i describe uses an empty anchor tag to allow a hover state for actual block elements (so rather than using an <em> and a <span> you can use the more semantically appropriate <h2> and <p> tags) … granted there is the extra markup of including the anchor tag twice, it displays more appropriately (imo) for text-only users.

  23. * strike “similar” … more like alternate … method i describe also requires js to work properly in IE 😛

  24. Right now im having a problem with this code. that it is messing up my alignment for my content box. Was wondering what I need to change to get the alignment normal in my case move it to the left.

Comments are closed.