DEV Community

Kevin Cox
Kevin Cox

Posted on • Originally published at kevincox.ca on

Things I Hate #2 — Fake Links

It is a common frustration to be using a website and encounter a link-like UI element that isn’t a real <a> (anchor) tag. Instead it is a <div> or a <span> that the developer has attached an onclick listener to. They have poorly reimplemented the most fundamental UI element on the web.

What is wrong?

It takes you to the target when you click on it, they were even kind enough to underline it so that you recognize it as a link! What more could I possibly want‽

What is wrong is that <a> is a subtly rich tag with a plethora of built-in features. It is more than a click-sensitive element with some styling. For example here is list of some <a> tag features that I use.

  1. Middle-click to open in new tab. (Some people use Ctrl-Click as well!)
  2. Find-in-page and navigate by pressing enter.
  3. Right-click to open in new window.
  4. Send link to another device.
  5. Share link with my friends.
  6. Hover to see where the link is going.
  7. Long press a link to bookmark it.
  8. Check the colour of a link to see if I have been there before.
  9. Use a shortcut to quickly filter through and activate links on the page.

And don’t forget that accessibility tools have excellent support for anchor tags. While you can mark up your fake link with a plethora of ARIA information it will only ever approach the accessibility of a native <a> tag.

My point isn’t that any one of these features can’t be implemented on your fake link. The problem is that there is an unknowable set of features that browsers (and other User Agents) implement for links. It is fundamentally impossible to implement them all! Not only because you can’t know all features that exist currently or may be added in the future but also because some features implemented by different browsers are mutually incompatible!

What to do instead?

Just use an <a>! (And of course make sure that the href attribute points to a URL that actually works!)

There is a common use case that requires a bit of work. If you want to handle internal navigation yourself (this can potentially be faster than doing a full-page reload, especially if your site is very heavyweight). Then you should still use an <a> tag, but you will require a bit of JS to disable the default behaviour for regular navigation.

Unfortunately there is no perfect solution here, I wish there was an onfollow event that we could hook for when a user activates a link in the “normal” way. Unfortunately semantic events are not present the web so we are left with the following:

mylink.addEventListener("click", e => {
    if (e.altKey || e.ctrlKey || e.shiftKey) return;

    e.preventDefault();

    // Do your link handling here.
});

Logically it is quite simple, ignore the event if any modifier keys are held (these are used by many browsers to open in new tabs or windows, which we will let the browser handle).

This even works for keyboard-based activation as that triggers a synthetic click event!

I don’t like that I need to hardcode this logic into my app, I would love to see a follow or activate event for buttons and links however this is the best solution I am currently aware of. If you have a better solution please let me know!

Top comments (0)