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 style sheet!) I thought it'd be helpful to show how to create this "block hover" effect.

Example of Veerle's link list block hover effect
Link hover effect on Veerle's blog

The Example

First, view my 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.

<div id="links">
    <ul>
      <li><a href="#" title="Text">Link Heading One
        <em>Description of link.</em>
        <span>Date posted</span></a></li> 
      <li><a href="#" title="Text">Link Heading One
        <em>Description of link.</em>
        <span>Date posted</span></a></li>
    </ul>
  </div> 

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

Large clickable boxes as navigation with CSS and DOM

Posted on: March 8, 2006 | 10 Comments

Recent Entries in "CSS"

10 Comments Posted

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!

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.

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.

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).

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.

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.

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.

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 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 - did you know that the W3C suggest it be used to mark up a dialogue between speakers?!

Thank you.

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. :)

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

good stuff, I looking for this a long time, its so simple :D but my config won't work ^^

Thank you very much for this info on how she did that.. Looks beautiful!

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.

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.

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.

Isn't the div superfluous? Why not use:

<ul id="links">...

This would be a good application of a definition list. This is clearly a list of links, and the descriptions and dates define the links.

While I think this approach is an interesting excercise I really think it's terrible to suggest it to be used in a real environment.

There are ways to get the :hover behaviour working in IE via Javascript, and it's a much better idea to use those, rather than creating awkward HTML.

http://www.xs4all.nl/~peterned/csshover.html
http://dean.edwards.name/IE7/

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.

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

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; }

why not look at veerles css file?

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.

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.

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.

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;
}

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.

  • strike "similar" ... more like alternate ... method i describe also requires js to work properly in IE :P

Nice tutorial, it is linked to by my site at http://www.tipclique.com It doesn't have many active members currently, but I think once people start using it to sort their favorite tutorials this will be one in the top.

Thanks,

Drixer

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.

mike – perhaps you can post a link to your test page so I can see what the problem is?

TOP STORES

Categories

Subscribe

Subscribe to my RSS FeedSubscribe to my Web Design Blog RSS Feed

Proud member of 9rules network