The a.block pattern

23-03-2011
Tagged html, css
TLDR: I explain how I use HTML anchors as block-level elements.

Wrapping block-level HTML elements inside an anchor (<a>) element has always worked fine, but used to be frowned upon. Standards dictated you should not put block-level elements inside inline elements. HTML5 has changed this, and now explicitly allows anchors to contain block-level elements.

Before HTML5 we could wrap, say, a <div> with an <a >, but it was considered invalid. Yet the wish remained to make entire areas clickable, rather than just a “Read more”-line. A larger clickable area improves CTR and reduces user mistakes.

The problem

Given a typical ‘story’ element, where a headline, thumbnail and short introduction text would link the user to a full article, here’s the effect you’d want to achieve:

<div class="article">
    <a href="/story"><img src="pic.jpg" alt="Story thumbnail"></a>
    <h3><a href="/story">Story title</a></h3>
    <p><a href="/story">Lorem ipsum dolor sit amet</a></p>
    <a href="/story">Continue reading&hellip;</a>
</div>

Script-based solutions

That sort of markup is terrible to write – let alone maintain. Javascript-solutions were concocted to keep markup clean, but still make the entire story-element respond to user clicks:

<div class="article">
    <img src="pic.jpg" alt="Story thumbnail">
    <h3>Story title</h3>
    <p>Lorem ipsum dolor sit amet</p>
    <a href="/story" class="bigtarget">Continue reading&hellip;</a>
</div>

And the script:

// dummy javascript code
$('.bigtarget').parent('div').click(function() {
    document.location = $('.bigtarget', this).attr('href');
});

The HTML5 way

With HTML5 it is now considered alright to do the following:

<div class="article">
    <a href="/story">
        <img src="pic.jpg" alt="Story thumbnail">
        <h3>Story title</h3>
        <p>Lorem ipsum dolor sit amet</p>
        <span>Continue reading&hellip;</span>
    </a>
</div>

That’s clearly the best-looking code, without repetition or confusion of intent.

However, doing so introduces a problem with styles, as we probably don’t want our image, heading and paragraph to look like links (you know, blue text, underlined, etc.). I therefore used the following pattern to counter this.

First, I introduce a class name to designate this is a special kind of anchor element:

<div class="article">
    <a href="/story" class="block">
        <img src="pic.jpg" alt="Story thumbnail">
        <h3>Story title</h3>
        <p>Lorem ipsum dolor sit amet</p>
        <span>Continue reading&hellip;</span>
    </a>
</div>

Using the block class, I can now reset the anchor’s contents styles. I could do so manually for maximum compatibility, but if you target only modern browsers1 you could use inherit:

a.block { display: block; }
a.block, a.block * {
    text-decoration: inherit;
    color: inherit;
}

…or something along those lines, depending on how you style your links.

Second, I want to give users a visual cue on the story’s affordance of clicking. Therefore, we need something that looks like a link, and the story element in its entirety needs the same interaction as a link — i.e. hover, focus, visited and active states.

I only want to style part of the story as a link, but I’m not sure which part. Maybe a “read more”-line at the bottom, or the heading… Since this might differ from case to case, I chose to use a generic class to indicate the link target:

<div class="article">
    <a href="/story" class="block">
        <img src="pic.jpg" alt="Story thumbnail">
        <h3>Story title</h3>
        <p>Lorem ipsum dolor sit amet</p>
        <span class="target">Continue reading&hellip;</span>
    </a>
</div>

I could just add the target class to any of the other elements as well.

I style the target-element the same as my regular links:

a.block .target {
    color: #009;
    text-decoration: underline;
}

Now, the block looks like traditional content with a simple link at the bottom, but the user gets a nice surprise when hovering over the story thumbnail or title also activates the link.

Of course, you could also implement this same effect using just descendent selectors, like so:

div.article a:first-child {
    display: block;
}
div.article a:first-child > span:last-child {
    text-decoration: underline;
}

…but this is clearly not as neat as throwing in some reusable class names. I have found the a.block pattern to be helpful in keeping my markup and styles uncluttered.

  1. Internet Explorer is known to not properly support the ‘inherit’ keyword.