About How :focus-within Doesn't Quite Work in Safari
It has been a long, long time since I implemented drop-down menus for a website. In my last job, all the websites had them and there was well-used code that we applied to this problem. But that was in the before times. In 2023, how does one go about creating drop-down (fly-out, some say) menus for a website if you’re not automatically going to fall back on a framework or a library?
:focus-within pseudo-class. At the time, this was a relatively new approach that was not supported in all cases. The attempt was abandoned in favor of our “tried-and-true” implementation, but I did not forget the attractiveness of a possible CSS-only solution. Today, with the pending need for dropdown menus on websites in my current job, I decided to give it another go.
My initial attempt was as shown in the CodePen below. The website for which I am developing this menu is based on Drupal, so the HTML for the menu is an unordered list of links inside a
<nav> element. Drop-down menus are nested unordered lists. Clicking on a top level option places the focus on the link; CSS styles for the list item containing the link use the
:focus-within pseudo-class to display the nested unordered list which is hidden by default.
In Firefox, this simple implementation works fine. However, it fails in Safari, and I cannot figure out why. In Safari v16, if you open the developer tools and force the :focus-within state on the list item, the dropdown will appear. But either the link will not capture focus when clicked or the focus on the link does not trigger the :focus-within state on the list item.
There is a fix for this. If I add the attribute
tabindex="-1" to the link, then everything functions correctly.
I wish that had been the end of the story.
Accessibility of this approach is a concern. I want to make sure that our website have accessible dropdown menus. A brief Google search resulted in a few articles describing how to create accessible dropdown menus:
- Dropdown menu example from Orange Digital Accessibility
- CSS-Only Accessible Dropdown Navigation Menu by Stephanie Eckles
- Accessible Dropdown Menus by Tristan Wilson
These examples of accessible dropdowns all use a
<button> element as the trigger for the menu. As I understand it, a button is more semantically correct in this instance and provides a better user experience to users browsing with the help of various assistive technologies. So I replaced the link in my example with a button.
Unfortunately, Safari once again has a problem. Here I thought a button element should be more agreeable for capturing focus and triggering the
:focus-within state on the parent list item element. Instead, the situation is worse. I cannot get the button to show the dropdown in Safari, no matter what attributes I add.
For now, I am going to try using a link with the
role="button" attributes to see if that will provide the desired level of accessibility. However, it would be nice if Safari would simply handle the
:focus-within state as well as Firefox does.
And no, I have not even tried Chrome yet. *sigh*