UPDATE: A more recent version of this article was posted on CSS-Tricks: How to Disable Links.
The topic of disabling links popped up at work again this week. Somehow, a disabled anchor style was added to our typography styles last year when I wasn't looking.
The problem is that there is no real way to disable links. Why would you even want to do it, links and navigation are the basis of the web?
At a certain point, it looked like people were not going to accept this fact and I started thinking of how this could be accomplished. Knowing that it would take a lot, I wanted to prove that it was not worth the effort/ code to support such an unconventional interaction, but I feared that by showing that it could be done they would ignore all my warnings and just use my example as proof that it was ok. Instead, I pushed back a little more. I got the sound of crickets as response, so not sure where this is going to land.
JUST DON'T DO IT!
A disabled link is not a link, its just text. You need to really need to rethink your design if it calls for disabling a link.
Yes, I know Bootstrap has examples of applying the .disabled
class to anchor tags, and I hate
them for it. At the very least they mention that the class only provides a disabled style, but this is just
misleading. You need to do way more than just make a link look disabled.
How to disable a link
If you have decided that you are going to ignore my warning and proceed with disabling a link, then
removing the href
attribute is the best way I know how.
Straight from the official spec:
An easier to understand definition from MDN:
Here is basic JavaScript code to set and remove the href
attribute:
Styling this via CSS is also pretty straightforward:
That's all you need to do!
That's not enough, I want something more complex so that I can look smarter!
If you just absolutely have to over-engineer some extreme solution, here are some things to consider. Hopefully you will take heed and recognize that what I am about to show you is not worth the effort.
CSS Only
First things first, like Bootstrap, we need to style our link so that it looks disabled.
First pass at our disabled link class. Setting color
to currentColor
should reset
the font-color back to your normal, non-link text font-color. I am also setting the mouse cursor to
not-allowed
to display a nice indicator on hover that the normal action is not allowed.
Already, we have left out non-mouse users that can't hover, mainly touch and keyboard, so they won't get
this indication. Next the opacity is cut to half. Next the opacity is cut to half. According to WCAG, disabled elements
do not need to meet color contrast guidelines. I think this is very risky since it's basically text at this
point, another reason I hate this. Lastly, the text decoration underline is removed as this is usually the
best indicator something is a link. Now this looks like a disabled link!
But it's not really disabled! A user can still click/ tap on this link. I hear you screaming about
pointer-events
. After all, isn't that what Bootstrap does?
Ok, we are done! Disabled link accomplished! Except, it's only really disabled for mouse users clicking,
and touch users tapping. What about browsers that don't support pointer-events
? According to caniuse this is not supported for Opera Mini and
IE<11. IE11 and Edge actually don't support pointer-events
unless display
is
set to block
or inline-block
. Also, setting pointer-events
to
none
overwrites our nice not-allowed
cursor, so now mouse users will not get that
additional visual indication that this link is disabled. This is already starting to fall apart. Now we have
to change our markup and CSS...
Wrapping the link in a span
and adding the isDisabled
class gives us half of our
disabled visual style. A nice side-affect here is that the disabled class is now generic and can be used on
other elements, like buttons and form elements. The actual anchor tag now has the
pointer-events
and text-decoration
set to none
.
What about keyboard users? Keyboard users will use the ENTER
key to activate links.
pointer-events
are only for pointers, there is no keyboard-events
. We also need to
prevent activation for older browsers that don't support pointer-events
. Now have to introduce
some JavaScript.
Bring in the JavaScript
Ok, now our link looks disabled and does not respond to activation via clicks, taps, and ENTER
key. But we are still not done! Screen reader users have no way of knowing that this link is disabled. We
need to describe this link as being disabled. The disabled
attribute does not work on links,
but we can use aria-disabled="true"
.
Now I am going to take this opportunity to style the link based on the aria-disabled
attribute. I like using ARIA attributes as hooks for CSS because having improperly styled elements is an
indicator that accessibility is missing.
Ok, now our links look disabled, act disabled, and are described as disabled. Unfortunately, even though
the link is described as disabled, some screen readers (JAWS) will still announce this as clickable. It does
that for any element that has a click listeners. This is because of developer tendency to make
non-interactive elements like div
and span
as pseudo-interactive elements with a
simple listener. Nothing we can do about that here. Everything we have done to remove any indication that
this is a link is foiled by the assistive technology we were trying to fool, ironically because we have
tried to fool it before.
But what if we moved the listener to the body?
Are we done? Well, not really. At some point we will need to enable these links so we need to add additional code that will toggle this state/ behavior.
That's it. We now have a disabled link that is visually, functionally, and semantically disabled for all users. It only took 10 lines of CSS, 26 lines of JavaScript (including 1 listener on the body), and 2 HTML elements.
Seriously folks, just DON'T do it!