the a element is broken

Though technically links aren't a requirement to make the internet function (you can get by on just urls), they are the primary reason why the web took off so gloriously. Linking is an essential part of every web page out there, without links we would be copying urls the entire time (or we wouldn't because who likes to work like that). But the implementation of links (the html a-element) has been broken since the very beginning of the web and with the addition of block-level links things only got worse.

the fundamental issue

The first argument is a pretty old one (I think I first read it more than 10 years ago). The link element does not fit into the axiomatic content-design-functionality tripod philosophy of the web. A link is not semantic, it tells you nothing about the content within, nor is it structural. Instead it provides functionality (it transports you from one page to another) and it tells you the absolute address of the content it wraps. Now I understand that not having it built into the html would've posed enormous problems (you don't want page linking behavior to be part of the javascript), but a couple of years ago a serious opportunity presented itself to improve the html link implementation.

A part of the now long-dead xhtml2 syntax proposed a different implementation for links. Instead of using a separate tag (which is little more than an excuse for setting an href attribute), the xhtml2 syntax stated that you could just set the href attribute on whatever element that needed to be linked. A splendid idea that was discarded because of backwards compatibility issues (and probably rightfully so), but at least theoretically this implementation made infinitely more sense than the current one.

the nesting issue

Another recurrent problem is that links cannot be nested. When browser detect nested links they go completely haywire, spewing out all different kinds of crap code (I can't guarantee these older results are still correct but I sampled the different variations in my how to make your browser vomit article a few years ago).

Conceptually I still believe there is little wrong with nesting links (deeper-nested elements appear on top of higher-up elements anyway, so there's no real problem there), but apparently it does pose a couple of technical difficulties that prove hard to work around. It's a real drag if you want to block-link an entire html node (like an post preview) but still want an immediate link to the comments of the post. No good workaround exists, unless pulling the direct link out of the post view.

the block-level issue

The thing that annoys me the most is more of a practical nature though. Even though linked states of components have visual variations, the fact that the a-element changes the dom structure of linked elements compared to unlinked elements means that you can't make proper use of the descendant combinator (>) for styling. There are 3 main ways to tackle this, but none of them is very solid.

To illustrate the problem, imagine I want to block-link the post previews on my homepage. The unlinked html code would look like this:

<article class="post"> <header> ... </header> <div class="main"> ... </div> <footer> ... </footer> </article>

A pretty straight-forward html structure (one I use for marking up content types all the time).


<a class="post" href="..."> <header> ... </header> <div class="main"> ... </div> <footer> ... </footer> </a>

One of the easiest ways to block-link a component is to simply replace the base tag with the a-tag (somewhat mimicking the xhtml2 ideology). It keeps the dom structure intact which at least in theory makes styling the component a lot easier and more robust to changes later on.

The problem is that you lose the semantic value of the base tag (article in this example) and once you're depending on html tags in your css selectors (you may have, and the switch between article and a tag becomes a real chore to manage in css.

outer wrapping

<a href="..."> <article class="post"> <header> ... </header> <div class="main"> ... </div> <footer> ... </footer> </article> </a>

Outer-wrapping the element helps to preserve child-selector constructions (like .post > header) by wrapping the a-tag around the component, but it introduces its own set of limitations. Context-dependent styling becomes a lot trickier (you can't just target .context > .post but also have to take into account .context > a) and when querying the dom for information you miss its link content when looking for posts (if you query for it won't include the a + href, a pretty big problem for syndication by scraping).

While this setup makes the most sense from a traditional point of view (this is how we have always linked things, wrap the a-tag around the object we want to link), it's far from ideal when dealing with the css practicalities.

inner wrapping

<article class="post"> <a href="..."> <header> ... </header> <div class="main"> ... </div> <footer> ... </footer> </a> </article>

The final option is to inner-wrap a component, placing the link directly underneath the root-tag. Like I mentioned before, this completely breaks child-selector structures in your css, which is a pretty big setback just for wanting to link a specific component. Even though less (or sass) can help you along, it's far from ideal and results in an overload of unnecessary css rules.

On the other hand, the link itself is enclosed by the article tag, which feels right from an html structural point of view (since the link contains the url for the detail view of the linked component). For that reason alone I've been using this option ever since block-linking was allowed.


I'm not happy with html links. From a conceptual point of view their implementation makes no sense at all. Even though I get the backwards compatibility issues, I feel that the current setup is not really sustainable, so some sort of path forward would be nice.

On top of that, it's pretty sad to see that one of the most essential elements of our language is so badly crippled and makes such a mess of our code. In general I'm glad html5 made the cut, but in some rare cases I wished that more ideas of the xhtml2 syntax had survived.