Preword: Here we are with yet another on of my angry rants on Accessibility.
If you haven't seen these before, the anger is just for fun, but the message is important, I am not actually angry 😋.
If you aren't sure where I am being silly just ask, I know sarcasm doesn't always translate well in the written word!
Why should I use a <button>
? A <div>
works!
Works for what? Sure it might work with a mouse, but a lot of people with disabilities rely on a keyboard, and a <div>
is not focusable.
Do you not care about people with disabilities?
Are you heartless?
Even an angry soul like me cares, so what is your excuse?
Obviously, you could add tabindex="0"
to the <div>
to make it focusable, but then you also need to add keyboard handlers for the Enter and Space keys (yes both, buttons work with space and enter!).
You also need to add focus indicators.
That all seems like a lot of work to me.
All of this can be solved with a <button>
.
As an added bonus, it will even interpret Enter and Space as a click
so you can just attach a click handler!
As a further super special bonus just for you, it also receives focus right out of the box! So you don't need extra tabindex
attributes cluttering your beautiful HTML.
But wait...there's more!
As well as gaining focus right out of the box, it also has a focus indicator by default, as well as a hover state! (although I would probably add your own versions as they aren't great out of the box!)
So even if you forget to add them, someone else has already done the work for you.
I know all that, but native <button>
elements are ugly, that is why I use a <div>
.
Let me drag you into the 21st century.
You can remove all the styling from a native button element using this magical thing called CSS.
Then you can make it look however you want! Isn't that amazing!
I know CSS is complicated and scary (I mean, you can't write HTML so you don't have a chance with CSS) so let me help you with a quick <button>
reset example.
A quick example
You don't even need a couple of the CSS properties I added below unless you are supporting IE9, but for the sake of 20 bytes you might as well have them.
button {
border: none;
margin: 0;
padding: 0;
width: auto;
overflow: visible;
background: transparent;
color: inherit;
font: inherit;
line-height: normal;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
}
A jsfiddle to showcase your new "styleless" button!
In the following jsfiddle you will see the <button>
and the <div>
look identical, but you can still press Tab and focus the button despite it not having tabindex="0"
...shocking!
The button in that fiddle is essentially a <div>
now, but with magical powers!
You can then apply all the same styles that you would have done with a <div>
...jackpot!
Obviously if you have been using a <div>
in place of a <button>
you probably need a reminder to make sure you set styles for :focus
and :hover
states too. I just reminded you, go do it now!
Yeah don't worry, I know not to use a <div>
, I use a <a href="#"
instead so it has focus states!
I can sum up my reaction to that statement in one simple emoji:
🤦♂️
In some ways this is even worse, you already know that a <div>
is not semantically correct and doesn't allow keyboard focus, why on Earth would you then think "I will use a hyperlink". I think it deserves a second facepalm...🤦♀️
This pattern is from 2008 people! It was necessary back in a dark time when we had IE7 and IE8 to contend with, a time when we only had HTML 4 and buttons couldn't be styled properly. Those days are behind us now! Rejoice in the wonderful world of HTML5!
But How do I know when to use an anchor and when to use a button? I hear you ask!
If you remember one thing remember this: "A hyperlink (<a>
) changes the URL".
It is essentially that simple, should I use a hyperlink or a button here?
Simply ask yourself "does it change the URL"?
-
Yes - use an anchor with a valid
href
-<a href="an-actual-url-not-javascript-void-and-not-a-lone-hash">
-
No - use a
<button>
.
Don't forget, you can still run some JavaScript before changing the URL, you can even use AJAX to load the new page in, but navigation (a URL change) means an anchor, otherwise use a <button>
.
I know a lot of you will now be saying "but what about X scenario"...you are wrong (probably, there is one use case I can think of...).
But that rule doesn't always work now, does it?
Oh, you are a smart one aren't you?
You know about the Achilles heel in my argument...you ask "What about a no JavaScript fall-back?"
Yup you are right, they are few and far between but they are valid. But notice that in any of those scenarios href="#"
would not be valid as it wouldn't fall back to anything!
For example, the following is an acceptable pattern for something like a button that opens an off-canvas menu on mobile, but has a sitemap as the fall-back for when JS fails:
<a href="https://yoursite.com/sitemap" role="button" class="button">Menu</a>
But you should add the role="button"
with JavaScript.
That way if there is no JavaScript (for example when a JS file request fails) it is still just a valid hyperlink as far as a screen reader is concerned.
When JS works (99% of the time) it will receive role="button"
and should be treated as a button and it all makes sense again.
Yet again I will repeat: for this pattern to work the URL should be a valid fall-back URL.
Oh and don't forget, you should also add an event handler for Space as a button works with Space and Enter if you do this (hyperlinks only work with Enter)!
If none of that made sense to you don't worry, I will do an actual (non-angry man rant) full article on this in the future that explains it all properly.
Why do we still have this problem?
Old tutorials New tutorials and libraries based on old and out-dated tutorials based on even older tutorials.
There are at least 3 articles currently in my feed with this exact problem (what do you think sent me into grumpy mode?!)
So if you are writing tutorials....learn HTML...it is really easy!
And if you can't learn HTML...find another profession!
Yes, even not angry me thinks this, you have no place building anything front-end website wise if you can't learn HTML.
It is the easiest thing to learn in front-end web development.
If you are a code newbie and want to build things for the web, learn HTML first, you will be light years ahead of the competition in only a couple of days!
Let's start calling people out!
Yes, I am advocating bullying. But nice bullying!
Any time you see someone use <a href="#"
as a <button>
, tell them they are a noob and show them the light. (don't tell them they are a noob, that is the angry man talking! Just lead them into the welcoming arms of semantic HTML).
Any time you see <div class="button"
- cringe, draw a deep breath and tell them the error of their ways.
OK but what could I possibly say?
You know what, I will make it easy for you, just copy paste this into the comments section under their article:
Great article but please can you use
<button>
elements for buttons.It makes the page more accessible for people who rely on assistive technology (generally people with disabilities).
As an added bonus it makes life easier for you as a developer!
Every article where we don't use semantic HTML means code newbies learn bad habits (as we all start with the "copy paste" phase, the best way to learn / get things done!) who then create websites that result in more people being excluded in this world.
Those same code newbies then have to unlearn bad habits you taught them once they start learning about accessibility. You are making things more difficult for them.
97.4% of websites have accessibility errors.
I am sure, given the rest of the article being so great, that you don't want to contribute to that problem."
Optional extra paragraph and GIF for particularly bad offenders or repeat offenders
"Oh and if you don't fix the article, the angry accessibility rant guy @InHuOfficial may pay your website a visit. You don't want that..."
(and before you ask, I am definitely not cool enough to justify comparing myself to John Wick! But this is my article so let me have my little fantasies, they ease the angry man syndrome you know!)
End rant
Once again this is mostly for fun, the message is important though, use semantic elements and make the web a better place for everyone!
If you are writing on dev.to or other sites be especially careful with any mark-up you release (that isn't meant to be "just for fun"), the impact is more significant than you think!
And on a serious note, if you think you have a scenario where you need to use an anchor as a button, mention it in the comments, it may be a valid use case I haven't come across or it may be that a decision elsewhere is "forcing your hand" to use the incorrect element. It would be great to explore that together!
For the Algo!
My new sign off experiment!
If you enjoyed this article, give it a ❤, if you thought it was special give it a 🦄 and above all, don't forget:
Leave a comment for the algorithm! (even if it is just to tell me to stop being so angry 😉!)