Published: December 03, 2022 • Updated: December 13, 2022 • 4 min read
Which HTML elements should we be giving a user to click? In this post, I’ll share some best practices for clickable elements.
To summarize:
Let’s get into it!
Peruse a JavaScript frontend, and you’ll find many clickable elements that are
not buttons or links: div
, span
, tr
, etc. Sometimes there are no actual
buttons in an application at all!
If this post convinces you of anything, let it be this: clickable things should be links or buttons. You have to make a case to do otherwise. We can bend more things than we think into one of these elements. Using links or buttons makes the document better because it will be more semantic and accessible.
Let’s look at each of those terms.
Semanticism is a goal in frontend programming of using tags that have meaning.
When you use a link or button element, you’re writing markup that has meaning.
Those elements mean something independent of the medium. Your intent will be
better understood by every consumer (all clients, and programmers reading your
code) than general tags like div
.
The React docs on accessibility make this case:
“Semantic HTML is the foundation of accessibility in a web application. Using the various HTML elements to reinforce the meaning of information in our websites will often give us accessibility for free.”
Not every tag can be semantic, but most can, and should be.
Links and buttons are more accessible than generic tags.
Assistive technologies are getting smart these days: give a div
a click handler
or even a class with the substring ‘btn’ in it, and some screen readers can
determine that it’s clickable. But why take that chance, when there’s
an accessible alternative readily at hand?
Buttons and links do different things. Use the right one in the situation you’re in.
Here’s a decent mental model: buttons “do something” and links “go somewhere.” But, this is getting blurry these days! In a modern JavaScript application, many clicks that “go somewhere” also “do” a lot of things.
Here’s an alternate mental model: what would the customer think is happening? When they click “log out”, what would be their mental model? “Go somewhere”, or “do something”? That’s what you should do.
A programmer knows that logging out is doing something: changing the state of authentication. A customer might think something similar– the application is doing something called logging me out. The fact that it “goes” to the login page afterward is maybe just a detail. I’d implement it as a button.1
A few more examples:
You aren’t going to always get it right, and sometimes, you can bend the rules. When it doubt, be consistent.
Clickable elements need signifiers.
In The Design of Everyday Things, Don Norman discusses affordances and signifiers. Affordances are what actions are possible; signifiers are perceptible signals about those actions. Links and buttons have clear signifiers. When you’re using something else, you need to add signifiers.
Link signifiers are universal. They are a different color, are often underlined, and have a pointer cursor that makes that little hand show up when you hover over them. Many have a hover state and most have a visited state.
Button tend to benefit from skeuomorphism– they look buttons in the real world. Many have hover states, some have pointer cursors, and some have processing states like spinners, changing text, or temporary disability when processing.
Clickable things that are not links or buttons need signifiers, too! Sometimes they are in a context like a menu where almost everything is clickable, and that’s enough. Other times, you might need to add a drop shadow on hover, pointer cursor, call-to-action, or hover state. Pick one or multiple.
A clickable div
without any signifiers is rarely going to be clicked on. Add
signifiers.
Here are a few examples:
Here’s one non-link/button example:
tr
because of table nesting rules,
but we want it to be clickable, so this is a rare exception to our first
argument. To compensate for not using a button or link, we’ve added signifiers
of a border, a hover state, and a pointer cursor. And we aren’t confusing the
UX with links or buttons inside the row that draw attention away from it and
fight for click captures.To summarize:
There’s a lot more to this, and best practices continue to evolve. That’s a good thing! But these principles have proven to be timeless and following them works.
This example UX problem is often implemented as something that looks like a link. Stay safe out there.
↩What are your thoughts on clickable elements? Let me know!
Join 100+ engineers who subscribe for advice, commentary, and technical deep-dives into the world of software.