Make a div clickable
We all dislike that links are so small, and hard to click. So of course we want to make the clickable areas bigger. Some would think that doing this with some CSS on the a-tag would be a good way, but then you can’t have block level elements inside it (you’ll get a validation error if you try to put headings or paragraph tags inside of links). So what’s a more general solution?
My take is to use a div instead, and use javascript, of course together with a good fallback. When clicking the div, find the first link inside it, and go to that URL. It’s simple, and with a few additional quirks, it gets really useful.
Javascript code (requires jQuery):
$(document).ready(function(){
var block = $(".teaser");
block.click(function(){
window.location = $(this).find("a:first").attr("href")
});
block.addClass("clickable");
block.hover(function(){
window.status = $(this).find("a:first").attr("href")
}, function(){
window.status = ""
})
});CSS for showing that the div actually is clickable:
.clickable {
cursor: pointer;
}
.clickable:hover {
background: #efefef;
}A clickable div demo is of course available.
How it works
- When the div (or other tag, you choose) is clicked, find the first anchor tag, get it’s href attribute, and go there. Relying on an actual link means you always have a fallback, so no cheating.
- When javascript is disabled, it just falls back to a regular block, where only the links are clickable.
- A class called “clickable” is set on the block to allow for javascript-specific styling, such as changing the cursor with cursor: pointer, something you don’t want to happen when the block isn’t clickable.
- The changing background color on hover is done with CSS, which I think is fair, considering the small percentage of users using IE6. Changing background color isn’t a must feature.
- Lastly, since we’re simulating a link here, it should show where the link is going. I’ve done this by setting the statusbar to the link location on hover, something that’s useful when it works (users can disable this in some browsers).
Hope that little snippet is useful for someone out there, I think it’s a good example of good use of javascript.
Ole (4 comments) ( 1 Jul 2009 )
Good work. I’ve used the bigTarget jQuery plugin so far, but your code is much more tiny…
Thanks for that, i’ll try this out.
grimen (1 comments) ( 1 Jul 2009 )
Great! I did some polishing (well, depending on what one is looking for):
(function($)
{
$.fn.clickable = function(options)
{
var clickable = this;
clickable.each(function()
{
var e = $(this);
e.click(function()
{
window.location = $(this).find(‘a:first’).attr(‘href’)
});
e.hover(function()
{
window.status = $(this).find(‘a:first’).attr(‘href’)
}, function()
{
window.status = ”
});
e.addClass(‘anchor’);
});
return clickable;
};
})(jQuery);
trovster (2 comments) ( 1 Jul 2009 )
It seems there are a few of us who have realised this progressive enhancement is really useful. Like Ole mentioned, my friend Leevi released his bigTarget jQuery plugin. At pretty much the same time I got my demo page up for the code I’ve been using for a while, check out my Fitted jQuery plugin which achieves similar things.
Zach Leatherman (1 comments) ( 1 Jul 2009 )
I’m not a huge fan of this approach, as it doesn’t allow things like right click to open in a new tab, or middle click for the same.
James Padosley had a good method for this:
http://james.padolsey.com/javascript/table-rows-as-clickable-anchors/
Emil Stenström (605 comments) ( 1 Jul 2009 )
@Ole, trovster, grimen: Yeah, I found your suggested plugins right after I posted. I’m not sure I need it in plugin form, I usually just use this for a couple of boxes on the start page, which means supporting a single class, and 12 lines of code, is fine. Thanks though.
Anon (1 comments) ( 1 Jul 2009 )
Why not just give links more padding? Making elements clickable that are normally not clickable leads to confusion and is not a behavior users expect.
Emil Stenström (605 comments) ( 2 Jul 2009 )
@Zach Leatherman: That’s a very valid concern. I’ll see if I can add middle-click to the snippet if I get the time. Should be possible to forward the event from the block to the link somehow.
@Anon: What kind of confusion? These are all extra features, that make things easier for the user. If you look at the example, you’ll see that more padding just doesn’t work. Bigger clickable area (which the design should reflect, of course), means easier for user to hit it. I see only good things.
Krijn Hoetmer (4 comments) ( 2 Jul 2009 )
Please try HTML 5, where you can have block level elements inside an
aelement.Emil Stenström (605 comments) ( 3 Jul 2009 )
@Krijn Hoetmer: That’s actually a really good idea. Why should validation put us down? The only downpart I see is that it wouldn’t allow me to have other links inside it (as in the example). Because I guess HTML5 doesn’t allow links inside links, right? But that’s not such a big issue. Looking forward to good HTML5 support in browsers.
Siegfried (17 comments) ( 6 Jul 2009 )
Interesting. But i hope that xhtml 2 will come faster. This will allow href attribs for any element. So making a div clickable in xhtml 2 is straightforward: <div href=”http://www.some.where.com”/>…
The better solution i think :)
Emil Stenström (605 comments) ( 6 Jul 2009 )
@Siegfried: XHTML 2 has been canceled, and will be replaced with HTML 5. So no href attributes in sight.
Krijn Hoetmer (4 comments) ( 13 Jul 2009 )
@Emil: It already “validates”, when you use the HTML5 doctype. You can’t have nested links indeed, but that makes sense in a way :) And it already works cross-browser today; you only need to put
display: block;on your links (and make sure to use closingptags, etc.), so it’s one of the safe parts of the draft you can already use, imho. The only problem this doesn’t solve is making entiretrelementshrefable, due to table parsing and the magic that involves. You still need JavaScript for that.Krijn Hoetmer (4 comments) ( 13 Jul 2009 )
Also, using this, you get
:hoverstyles for free (without using JS hacks) in IE6, since that babe only understands:hoverona[href].I only wonder how search engines and AT work with this. “Click here” links clearly suck, but perhaps linking entire blocks of text, including headings, sucks as well. Would using
title=""on the link solve that? Somebody should do some study in that field :)Emil Stenström (605 comments) ( 15 Jul 2009 )
@Krijn Hoetmer: Great comments, you know a lot about stuff :) A search engine experiment with block links would be interesting. My guess is that the more words you have inside your link, the less weight each of them have. So for SEO, this might not be the most optimal solution. On the other hand, search engines care about words around a link too, so I’m not sure how much of a difference it makes.
Anders Ytterström (21 comments) ( 15 Jul 2009 )
In really extreme cases (that is, 80+ teasers) further enhancements can be done by letting a global click listener do the job with event delegation.
That will save a few buck on DOMready, especially in IE which is really slow in comparison.
Stevie D (6 comments) ( 23 Jul 2009 )
Brilliant! I have been doing this manually on my website for a few years, just adding an
onClickevent to the containingdiv– see website link for example. But this looks like a better solution, means I don’t need to worry about putting in the links twice every time.It depends on the nature of the content. In some cases, extra padding, leading or spacing will do a good job. In other cases, it helps to make surrounding content clickable. For example, on my website, there is a ‘panel’ that contains several items, and making the entire panel into a link makes it easier for users to select it – while, of course, retaining on old fasioned anchor on the first line for accessibility and spiders.
By applying
:hoverproperties to thediv, you give the visual affordance of a link to users (hand cursor, change of colour), so there should be no problem with unexpected behaviour.Emil Stenström (605 comments) ( 23 Jul 2009 )
@Stevie D: Nice to see that my scribbling is of use to someone :)
Andreas (15 comments) ( 24 Jul 2009 )
Simply positioning an a-element absolutely on top of the div with a width and height of 100% would achieve the same thing, no? _And_ it would act exactly the same as a real link (as it _is_ a real link).
I’ve done it this way before though as well, just a thought.
Regarding the JS-only CSS; I’ve used a js-enabled/js-disabled class on the body-element for ages now and it’s perfect for things like this.
I add the js-enabled class immediately after the opening body-tag so there’ll be no lag for the JS-only styling:
<body class="js-disabled">
<script type="text/javascript">
document.body.className = 'js-enabled';
</script>
As any performance-aware front-end developer I include all my JS before the _closing_ body-tag so it normally takes a couple of seconds before it kicks in. Giving body the js-enabled class at the top avoids styles blinking in though.
Emil Stenström (605 comments) ( 24 Jul 2009 )
@Andreas: It’s actually not exactly the same, as it has some strange side effects. Since the image covers all the text and images in the teaser, you can select or save the text or the image. And you can’t have more than one link in the same teaser, something that might matter for some (although few) people. On the other hand you get the possibility to middle-click the link, and all that.
Nah, I still like the HTML5 solution (see above comment) best I think.
Alex (22 comments) ( 21 Aug 2009 )
Do you think that by using this javascript method the SEO of that page will remain the same? Google has some issues reading javascript..
Anyway the demo looks great!
Emil Stenström (605 comments) ( 22 Aug 2009 )
@Alex: This way of doing this is unobtrusive, which means that even if Google wouldn’t read the data, it could still find and parse the link.
Alex (22 comments) ( 23 Aug 2009 )
@Emil, if that’s cleared, how can we make the link to open in a new tab/windows on right click?
Emil Stenström (605 comments) ( 24 Aug 2009 )
@Alex: Unfortunately, there’s no easy way to do that to the whole block. Though you could right-click on the real link, and do what you want there.
Alex (22 comments) ( 25 Aug 2009 )
@Emil, sorry i noticed that the real link retains it’s capabilities only after i’ve posted my last comment.
What i really like is that even if javascript is disabled you don’t get any error messages and the div block remains as if there is no javascript there.
Lewis Litanzios (15 comments) ( 17 Oct 2009 )
Yea, the “1’s” in pagination are a culprit here – pet usability hate of mine!
I used this typa technique recently on a ‘Read more…’ link: http://is.gd/4n09N (pulling in the post title URL and then hiding the title).
Kristopher (2 comments) ( 19 Jan 2010 )
Nice! I love the fallback method and using the first link, instead of just hard coding some URL on the div. Very cool!