Reinventing The Hyperlink
Hi everybody! I've just done a lot of cocaine on the company expense account and I want to talk to you about navigational action controls called "hyperlinks" and how to design them into your enterprise-level web application portfolio. YEEEHAWWW.
What is a hyperlink?
Back in the days of websites, long before The Web App Space, a boffin called Tim Berners-Lee invented something called the "anchor", which looked like <a>
and was a type of HTML element. It was called an "anchor" because it took you to places much like a boat would. Tim Berners-Lee often sailed boats into Switzerland to visit the LHC, you see.
Because anchors linked to things (different web pages or parts of web pages) we took to calling them "links". The W3C added "hyper" as a prefix to increase the element's appeal to infants and simpletons. This is what traditional hyperlinks looked like:
<a href="http://www.yahoo.com">Yahoo master domain portal</a>
We've come a long way since then and learned many high impact, transferable lessons. The most important of these lessons has been about performance. The performance problem with the above <a>
element is clear. Let me explain:
Because the hyperlink <a>
is recognized by your web browser, the browser will add styles to it, making it look like a hyperlink. This is fine for kids and amateurs, but we don't want hyperlinks to look like hyperlinks because then people will think we don't have any of our own, paradigm-shifting design ideas. We have to override the styles the browser has done for us (thanks, browser, but I think that's our job!) before we start adding our own.
a {
color: inherit;
text-decoration: none;
}
a:focus {
outline: none;
}
Adding these reset styles is costly in development time and, worse, results in us cruelly and irresponsibly sending dozens of additional bytes to the poor user's computer. This shall not pass! Wow, that coke really hit the spot. Right… to circumvent this bothersome necessity we need to choose an element which the browser does not recognize; one which it can't tamper with behind our backs. Fortunately, there is just such a template element, called <div>
:
<div href="http://www.yahoo.com">Yahoo master domain portal<div>
There is a minor issue here. Not just the style but the behavior of the traditional hyperlink is now omitted. In other words, clicking the <div>
won't do anything. I don't have any data in front of me, but I'm going to go ahead and assume this is bad for UX.
Confronted with this problem, some developers would cut their losses, conceding that the cons outweigh the pros, and go back to using Tim's original anchor thingy. Those developers don't do enough cocaine. If I can see through time, I can reinvent HTML! To retroactively preinstate [sic] the behaviors and semantics we just removed, we need to do a number of things. Let's go through each of these in turn.
1. Make the div focusable
Some people use keyboards to navigate websites instead of computer mice. It's not my bag at all, but whatever floats your boat. Just don't rub my face in it. No, but seriously, some of my best mates are keyboard users. That's their choice and they're entitled to it. Where was I? Oh yeah: <div>
s can't be focused (selected with a keyboard) like <a>
s are by default. To make them behave this way, you need to add a new attribute — tabindex="0"
.
<div href="http://www.yahoo.com" tabindex="0">Yahoo master domain portal<div>
You'll also need to create a focus style for that <div>
, much like the one we were trying to avoid having to reverse engineer by making the element a <div>
in the first place. This is fine, unironic and totally makes sense. Also, gzip, so shut up.
2. Give it a styling hook
Before we can do that, we need to add a styling hook to our <div>
. We need to be very careful how we choose our styling hook so that it makes semantic sense to each of the other 1,700 developers working on the project that uses it. Of course, using an actual <a>
would have been quite transparent, but that ship has bolted. Let's go with .link
.
Actually, .link
is good but it's not very well name-spaced. What if our project and another project inexplicably get put in the same web page and start having sex with eachother? You didn't think of that, did you! Let's also add a class of .our-project
(replace with your project name) to help discern between the two UI libraries after they've formed a sordid flesh-mass.
.link.our-project:focus {
outline: thin dotted;
}
3. Create a surrogate href
The <div>
element has a bug: When you give it an href
attribute, the attribute doesn't do what it's supposed to — send the user to the URL when they click the <div>
. This is because browser vendors are Lazy Satanists™.
To recreate this behavior we are going to use a javascript click handler. This is perfectly reasonable because, under all circumstances, users have javascript running in their browser and there are never any errors or problems. Thank you.
<div class="link our-project" onclick="window.location.href='http://www.yahoo.com'" tabindex="0">Yahoo master domain portal<div>
Excellent! We're almost there.
4. Adding the semantics
For reasons I cannot quite fathom, when you don't use an <a>
element, the browser's accessibility API doesn't communicate the <div>
to assistive technologies as an <a>
. To do this, you need to spoof the link semantic with a WAI-ARIA role. You know Aria Stark out of Game Of Thrones? This has nothing to do with her. You know the motorcycle helmet manufacturer Arai, whose domain, believe it or not, is whyarai.co.uk? It has nothing to do with them either.
<div class="link our-project" onclick="window.location.href='http://www.yahoo.com'" tabindex="0" role="link">Yahoo master domain portal<div>
Now, when a keyboard user with a screen reader running focuses the <div>
, it will say "Yahoo master domain portal link".
Conclusion
So, to summarize, we've taken an inert <div>
element, made it focusable by keyboard, given it a styling hook to differentiate it from other non-link-like <div>
s, given it the same :focus
style an <a>
element would have by default, approximated standard link functionality using the addition of javascript and provided link semantics in the accessibility layer for our pseudo-hyperlink using WAI-ARIA.
But what is the outcome? We have proven that Tim Berners-Lee is no big deal and I could have him any day and my nose is bleeding and oh no I'm not right.
The Takeaway
It's Friday, so I'm getting a curry. Thanks to @codepo8, @yatil, @g16n, @stommepoes, @HugoGiraudel, @RogerJohansson, @stevefaulkner et al for inspiring this abomination. @Flocke has made a gist with even more wheel reinvention involved, Satan help us.