You probably know overflow: hidden, overflow: scroll and overflow: auto, but do you know overflow: clip? It's a relatively new value for the overflow property, and with Safari 16 being released later this year all evergreen browsers will support it. So what does it do?
When going somewhere does a thing: on links and buttons
At the Fronteers conference, Manuel during his presentation did an exercise on building HTML that seemed fairly straightforward. On the site of Max Böck there's a thing you can click to open up a theme selector. What's that thing?
Of course, it's a button! Because it opens the theme selector at the top of the page. It does something! Add an aria-expanded to the button, make sure focus is set and you're good to go. It's obviously a button.
But what if it's not?
After Manuels excellent talk I was discussing this with a group of folks and I was adamant that it obviously was a button because it clearly opened a thing but… I didn't have a great argument for why it also couldn't also be a link. After all, all the arguments for a link are pretty sound. It stuck with me and in this article I want to explore both.
When to use links and buttons
The "common" logic for when to use links or buttons is as follows:
- If it goes somewhere, it's a link.
- If it does something, it's a button.
But if you ask me, those two things aren’t always mutually exclusive. I'll give implementation examples of both that I think are fine.
What we're building
The functionality we're building is the following: The top right button on mxb.dev opens a theme selector at the top of the page, and the theme selector has a close button that closes it again. That's it. Here's a video:
Using a button
This is the example Manuel gave and it's essentially the same as what I wrote in The perfect responsive menu.
The button looks like this:
<button aria-expanded="false" aria-controls="theme-selector">
Open Theme Selector
</button>
and the theme selector looks like this:
<div id="theme-selector" hidden="true">
… pretend there's a theme controller here
<button aria-expanded="false" aria-controls="theme-selector">
Close
</button>
</div>
Then when clicking the button, using javascript, the hidden
attribute of theme-selector
is removed, the aria-expanded
of the button is set to true, the JS moves the focus to the theme selector and then adds some CSS makes the theme selector appear (in the live implementation it's using an additional class, but you could also use the [hidden]
attribute being there or not instead).
In the theme selector, we have a close button that does the same in reverse.
Here's how it works in a codepen:
See the Pen
Button opening theme selector by Kilian Valkhof (@Kilian)
on CodePen.
Using a link
Okay, here we go. Why this can be a link: Links go somewhere, including different parts of the same page. So we can add a link that goes to #theme-selector
:
<a href="#theme-selector" id="theme-selector-controller">
Open Theme Selector
</a>
Using the :target
pseudo-class, we can make the theme controller appear after clicking the link:
#theme-selector:target {
display: block;
}
This will make the theme selector stay open while we interact with it. Inside #theme-selector
we add a second link that links back to our original button:
<a href="#theme-selector-controller">
Close Theme Selector
</a>
After clicking that, the #theme-selector
no longer matches the target, so it's hidden again. You can see it in action here:
See the Pen
Button opening theme selector by Kilian Valkhof (@Kilian)
on CodePen.
What's wrong with the link solution?
The browser gives us all the building block for a link solution. It works without javascript and as far as I can tell, the accessibility is decent too: using display
means the theme selector is hidden from assistive technologies and the browser itself makes sure the focus is managed.
The only things you lose is that the "button" is no longer aware of the expanded status and can’t be used as a toggle anymore. The toggle functionality I don’t have a solution for, but you could also say that now that the browser is maintaining a target
that's what holds that status.
In short, it's simple, doesn't need javascript, manages focus and the link clearly goes somewhere. It follows all the rules.
So why do I still prefer the (much more complex!) button example?
Addendum
Here’s what Ben had to say about this: the above is accurate, but it’s not something he would recommend in practice for a few reasons:
- Buttons can explicitly convey the expanded/collapses state, which is useful information in itself.
- Links and buttons have different keyboard triggers (both can be triggered with enter but buttons can also be activated with a space) and if you’re a sighted used, you might expect a button and be surprised when space does nothing.
He also brought up the point of links opening in a new tab when you middle-click. Does it make sense to have that functionality on a new tab?
All in all, he helped me understand why I still preferred the button and explained it as such: links are a semantically okayish way to do this; buttons are a more semantic way to do it
. Thanks Ben!
Thanks to Manuel and Ben for feedback on drafts of this article.