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