Three rules of the links
If you desperately want to put
# or something similar in a
href attribute, calm down, take a deep breath and use a
Buttons work with
:active styles and catch focus when tab’bing just like links do. Unbelievable!
If you really want to put
onclick="location.href='...'" in your element, stop, take a breath one more time and make a link. Now people can open your link in a new tab, use context menu functions, and even see the adress it points to just by hovering the mouse. Astonishing!
The only case when you can (and should) bind a js handler to a link – if a link actually leads somewhere. In this case, the handler should only trigger for left mouse button clicks without modifier keys.
Classic example: photo thumbnails. When you click on a thumbnail – large photo is shown on top of the content. If you click it with the mouse wheel or ctrl-click it – new tab with large photo is opened. Context menu also works just fine. Users with disabled / broken js get a working link on a photo. Everybody is happy:
<a href="photo.jpg" class="preview">
JS + jQuery:
// If it's not LMB or if a modifier key is pressed – do nothing.
event.button !== 0 ||
// Otherwise prevent the default action
// and execute our function (e. g. show photo)
In IE8 and lower, click events have
button property always set to
0. As a result, middle mouse button clicks also pass the check, but everything else is working just fine.
I wouldn’t make a fuss over this, but if you really want to get it working as intended, you may try. No need, IE8 is long dead.
There are many more cases where you should keep the functionality of a link. Here are some good examples:
VK’s paginator switches pages asynchronously, but still allows you to open a specific page in a new tab.
Login / registration forms
Reddit's login & registration form opens in a popup on top of the current page when clicked with left mosue button, and in a new tab when clicked with the mouse wheel. Unfortunately, they don’t check for modifier keys.
I accidentally came across this one when metacritic's scripts refused to load for me. Expand button under user reviews is, in fact, a link with a GET parameter, e. g.
Twitter resolved to follow the straight and narrow and began to gradually correct their rubbish. We can finally open user profiles in a new tab – good. Refresh button in the sidebar and compose new tweet button are both using
button element – also good (would be actually better if the last one was a link leading to a separate page with a form to compose a new tweet).
Same situation here. It’s not the same mess it used to be a while ago, but there’re still things to fix. Cycles menu on top of the home page still uses
data-dest="stream/circles/p4765f1c30e7d2c98" nonsense istead of normal links, and the userpic in the upper right corner is a link with my favourite
hrefs, none of the links can be opened in a new tab. They made async navigation via history states, but, it seems, they never heard of the tabs. It’s fiiiine, one tab is more then enough for an average hipster, right?
button for actions within the page,
a for links and actions that have a fallback URL.