Improve Usability and CTR: Make an Entire List Item Clickable

Published January 12, 2010 by CSS Newbies.

I was recently working on the navigation for a new WordPress site (to be announced later) and I encountered a bit of a conundrum when it came to my category navigation.

I had developed some snazzy PHP/WordPress scripting to output my category information into a list containing both the category name as well as the category description. It was a nice way to show people what categories the site had, as well as offering some insight into what the category might contain. The code looked something like this:

<ul id="categories">
	<li id="cat-1">
		<h2><a href="/some/where/">Category One</a></h2>
		<p>This is a description of category 1.</p>
	</li>
	<li id="cat-2">
		<h2><a href="/some/where/else/">Category Two</a></h2>
		<p>Category 2 description goes here.</p>
	</li>
	(...and so on...)
</ul>

I styled it such that the style changed when the user hovered over the list item (as in the image above). But while the list item contained a lot of information, the link to the category (inside the heading) — and therefore the actual clickable area — was rather small. I wanted the entire list item to be clickable.

And this isn’t a purely aesthetic choice, either (although that had something to do with it). It’s a usability concern. If I wanted my entire list item changed on hover, people would expect that clicking the list item would elicit some sort of response – this is the way navigation works in most corners of the web. But in this case, only those fortunate enough to click the anchor inside the heading tag would get anywhere. Not good.

Further, it stands to reason that the larger your links are, the more likely someone will click on them. Fitts’ law suggests that the time it takes to successfully click on an object is a function of the distance the mouse is from the object and the size of the object. Thus, the larger the clickable area, the higher the click-through ratio (CTR).

This line of reasoning left me with three options:

  1. Wrap the contents of the entire list item in an anchor tag. This isn’t ideal, because an anchor tag is an inline element, and inline elements technically shouldn’t contain block-level elements (like heading or paragraph tags).
  2. Wrap the contents of each block-level element in an anchor tag. This also isn’t a great solution, because it grows my code and requires me to style several different links.
  3. Use jQuery to do what I needed.

Can you guess which one I chose? If you selected option #3… well, you’ve visited this site before.

Our jQuery Script

This tiny snippet of code makes it all happen:

$(document).ready(function() {
	$("#categories li:has(a)").click(function() {
		window.location = $("a:first",this).attr("href");
	});
});

What this does is assigns a new click function to every list item in our categories list that contains (“has”) at least one anchor tag. When someone clicks on the list item, it redirects the browser using window.location to the location indicated in the first anchor’s href.

I’m using an neat jQuery trick here I haven’t talked about before:

$("a:first",this)

The “this” in the code above is a context selector, which is limiting the area in which we’re looking for the first anchor tag to the element that was just clicked. There is always a context applied to every jQuery expression you write: if you don’t specify a context, it uses the current HTML document. Here we’re limiting the context to the just-clicked list item, which reduces the complexity of our search (and presumably, calculation time) considerably.

That’s it? Yep! Five lines of code and you’re done! You can see a demo of this technique here.

A jQuery Plugin Alternative

Once I started working on this solution, I discovered that there’s already a jQuery plugin called BigTarget that does something rather similar to what I’m doing. If you’re in to jQuery plugins, definitely give it a look-see. If you’re planning to apply this in a lot of places, it’d probably speed up your development time. For my one-off use, however, I think five lines of code are preferable to a large plugin.

13 Responses

  1. David Hucklesby (reply)

    You could also use HTML5, which allows A tags to wrap both heading and paragraph. I believe this was added to HTML5 because it is both useful and enjoys 100% browser support.

  2. Rob Glazebrook (Author) (reply)

    I’ll be excited to see HTML5 grow in browser support, for reasons just like this.

    Until then, I’ll probably stick to XHTML. I recently tried developing a site in HTML5 using a bunch of the new tags, only to discover that CSS support on HTML5-specific tags is atrocious. I gave up and converted it back to XHTML.

  3. Brett (reply)

    Nice code. A simple, excellent solution.

    I might just add ( for the sake of those who do not know )that this is perfect for a small number of items in a list, but for a larger list (say a page with 40 blocks of this nature) I believe you could attach the click event to the ul and use event bubbling to determine which element was clicked on and redirect the same way. That way you’re attaching one click listener to the entire list, instead of one click listener to each item in the list – more efficient.

    And if you had a setup that was dynamically adding items to that list after the initial page loading you could use the .live() function attached to the ul (I do believe).

    If the listener won’t attach properly to the ul you could wrap the entire ul in a div and attach the listener there for event bubbling – it seems to me I had an issue with this before – can’t remember for sure.

    Anyhow, I’ve been following your blog for some time – excellent work – I really enjoy it. I’m just glad I finally found something I could add!!!!

  4. Rob Glazebrook (Author) (reply)

    Excellent addenda, Brett! You’re right in that this is tailored for a smaller-style list. I built it for a list containing five elements, and thus didn’t bother to complicate my code to improve speed. :)

  5. Pingback: CSS Brigit | Improve Usability and CTR: Make an Entire List Item Clickable

  6. Jan-Philipp (reply)

    Hi Rob, its a very nice solution you build. Just one thing, if I’ve deactived Javascript, the blocks will still seem like a link itself (caused by the li-hovers and cursor:pointer stuff). I dont think thats very user friendly, because a user with deactivated or blocked Javascript might think of a link, but by clicking he wont find one (only the heading is a real link).

    1. Rob Glazebrook (Author) (reply)

      That’s a good point, Jan-Philipp. One way around that might be to put the “hover” CSS styles in a separate class, and then assign that class to the clickable areas using jQuery.

  7. Menno Was (reply)

    This tiny script is great for increasing CTRs. Thanks a bunch! I combined this with the CSS3 rounded corner + gradient on hover.

  8. Zak (reply)

    Howdy! This post could not be wriotten much better!
    Looking through this article reminds me of my previois roommate!
    He continually kept preaching about this. I aam going tto forward this post to him.
    Fairly certain he’s going to have a great read. I applreciate you for sharing!

    Feel free tto surf tto my web bloog … garage floor tiles
    (Zak)

  9. review (reply)

    No matter if some one searches for his necessary thing, so he/she wishes to be available that in detail, therefore that thing is maintained over here.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>