Mayank RSS

When will Apple focus on Safari?

In a regular browser in a regular operating system, interactive elements on a webpage can be focused by tabbing to them (e.g. using a keyboard, joystick, or switch control) or by clicking on them (e.g. using a mouse, trackpad, or your finger).

This makes sense! Perhaps too much sense for Apple.

Keyboard navigation

On macOS, only text inputs and listboxes can be keyboard-focused by default. You need to explicitly enable “Keyboard navigation” in system settings to be able to focus buttons and links. (This setting might be named differently across different versions of macOS, but its functionality remains the same.)

This might sound like a big deal if you’re learning this for the first time. But in practice, keyboard users have very likely enabled these settings already. It would be nice if it worked consistently out-of-the-box, but at least there is a solution that does not require changing how we code websites.

Pointing devices

This is where all hell breaks loose.

On macOS, Chrome and Firefox will focus all interactive controls on click. This includes inputs, buttons, links, and even elements with tabindex="-1".

Safari, on the other hand, does not focus buttons and links (and some other non-text inputs, such as checkboxes and radio buttons) when clicked. Worse even, the focus even gets lost altogether. There is no user setting available to change this behavior.

This is a big problem when building anything more complex than a small static webpage. Building highly-interactive web applications with accessibility in mind often requires moving focus around. Accessibility is already too difficult, and focus not working consistently makes it even more difficult than it should be. For example, when a dialog or menu is closed, focus should generally return to the button that triggered it… which is not possible if the button literally does not get focused. (Native <dialog> can handle this case automatically, but only if opened with showModal and only if triggered with keyboard.)

There was a bug filed all the way back in 2008, which was closed as “wontfix”. Apparently, Safari is “behaving as intended”.

To quote an Apple engineer:

Buttons can’t be focused via keyboard by default, for example, and it’s non-sensical for a button to have a focus.

Wow. 😐

Personally I think the macOS behavior is what’s non-sensical, but I won’t get into that today. I care more about the web, in huge part because of the promise of cross-platform cross-browser consistency.

Another Apple engineer said:

Mac users expect the focus to remain in the text field if you click on a button.

I’m a Mac user and that’s not what I expect at all. I’m constantly bothered by the inaccessibility and UX papercuts of macOS, but again I digress. What I do want to highlight is that this is merely a theoretical argument, and one that’s been easily proven false by another bug filed in 2021.

To summarize: Clicking on a button in Safari not only does not focus it but also removes focus from a previously-focused element. Instead of fixing this, Apple first spent more than a decade defending it (without testing it, presumably) and has now spent more than two years ignoring it after their theoretical claims about consistency were disproved.

All this while, websites that work everywhere else continue to break in Safari.

Workaround

Thankfully, there is a relatively simple workaround: add tabindex="0" to all buttons, links, and non-text inputs. This will force them to be focused when clicked.

Code snippet
<a href="#" tabindex="0">…</a>
<button tabindex="0">…</button>
<input type="checkbox" tabindex="0" />

This should probably be handled in your design system or component library, to avoid having to repeat it every single time.

If you don’t want to (or can’t) manually add tabindex everywhere, you could write a client-side script that does it for you. You would probably need to bring in mutation observers to also handle elements that are inserted after page load. At that point, it might be better to instead use event delegation and manually call .focus() on click or mousedown. I’ve created a CodePen showing a basic implementation and comparing different techniques. You can test this Pen on your various Apple devices to get a feel for it.

Last time I looked into this issue, I vaguely recall tabindex="0" being insufficient on iOS, because Safari would forcibly blur buttons after click. Fortunately, this issue does not seem to be reproducible in iOS 17. If you are currently relying on some JavaScript-heavy workaround, such as Nick Gard’s polyfill, you might be able to remove it.

It’s important to remember that while this may fix the issue on your site, it is still a workaround that we can’t expect every website to add. The majority of developers do not own an expensive Apple device and may not even realize that their website has Safari-specific issues. The onus should be on the multi-trillion dollar company to fix the issue instead of ignoring it.

Suggestion for Apple

Things really don’t have to be this bad. The solution is incredible simple:

Stop fucking with focus. At minimum, make clicks (and taps) focus all interactive controls on the web. Ideally, also make them keyboard navigable by default.

While we’re at it, stop fucking with checkboxes too. Seriously.

Too bad no one at Apple can hear me over the sound of their money-printing machines.