If that blue lozenge isn’t a button, we’re gonna fight
The Great Button Betrayal
There’s a special kind of betrayal that happens when something looks like a button… but isn’t.
You hover. Nothing happens.
You click. Nothing responds.
You try the keyboard. Nada.
Maybe it was a <div>. Maybe a <span>. Maybe some text in a pill-shaped bubble someone styled to look “clickable.”
All you know is: You were led to believe. And the button let you down.
Picture this: You’re rushing to submit an important form before a deadline. That big blue “Submit” button looks perfect, obvious, ready. You click it. Nothing. You try again. Still nothing. You check your connection, refresh the page, try different browsers. The problem? It’s not actually a button at all. It’s a <div> dressed up to look like one, and the JavaScript that was supposed to make it work broke somewhere along the way.
This isn’t just annoying – it’s a real barrier that affects everyone, but hits some users harder than others.
Here’s the Thing: HTML Already Has a Button
What developers write (thinking they’re clever):
<!-- Bad: Looks like a button, acts like disappointment -->
<div class="button" onclick="submitForm()">Submit</div>
What users experience:
- Mouse users: Maybe it works?
- Keyboard users: Can’t reach it
- Screen reader users: “Submit” (no context it’s interactive)
- Mobile users: Tiny tap target, no native behavior
It’s like building a door that looks exactly like every other door, but when people try to open it, nothing happens. They push, they pull, they look for a handle that isn’t there. Meanwhile, there’s a perfectly good door right next to it that works exactly as expected.
What you should write:
<!-- Good: An actual button that actually works -->
<button type="submit">Submit</button>
A real, semantic HTML button:
- Works automatically with keyboard (Enter and Space)
- Is announced correctly by screen readers
- Supports focus states by default
- Can be disabled properly
- Submits forms without JavaScript
Fake buttons made from <div> or <span>? They don’t do any of that. Not without extra code. And even then, they’re fragile.
If it looks like a button, it should BE a button.
Visual Feedback: Make It Obvious
When someone interacts with a button, they expect feedback:
/* Good button feedback that doesn't suck */
button {
/* Base state */
background: #007acc;
color: white;
border: 2px solid transparent;
transition: all 0.2s ease;
}
button:hover {
background: #005a9e;
}
/* Erik Kroes' Universal Focus State */
button:focus {
outline: .375rem double black;
box-shadow: 0 0 0 .25rem white;
border-radius: .125rem;
}
button:active {
transform: translateY(1px);
}
Let people know: “Yes, this is clickable – and yes, it worked.”
Links vs. Buttons: Know the Difference
This one’s simple:
- Links take you somewhere
- Buttons do something
<!-- Link: Goes to another page -->
<a href="/about">Learn more about us</a>
<!-- Button: Makes something happen -->
<button onclick="openModal()">Open settings</button>
<!-- Never use an a tag for a button function -->
<a href="#" onclick="deleteAccount()">Delete account</a>
When you use the wrong element, you break expectations. Screen reader users hear “link” and expect navigation. Keyboard users press Enter on links but Space on buttons.
Get it right, and everything just works.
→ Want to dive deeper?
- MDN: The button element – Everything about <button>
- Inclusive Components – Real-world patterns that work