I’ve been spending a bunch of time side-tracked working on focus-related things these last couple weeks, and there have been a few significant changes that I hope will make both web developers and users happier.

There are various goals that I tried to accomplish, I will try to explain the reasoning for them, and then drop an executive summary of the changes below.

First, there will be no change for natively-styled controls. These are the default and work reasonably well, with all the caveats that native theming brings. So to the extent possible they should remain looking native / we shouldn’t regress their rendering.

With that out of the way…

Preventing missing focus indicators by default

This was my main goal (that is, fixing bug 1311444).

Different platforms have different conventions on when to show outlines (more on this below). One thing is clear though: When navigating using the keyboard, missing focus indicators are a bug.

When these are hidden by default by the browser, it should be fixed, and that’s what I did. This was a bit harder than it seems (as usual) because we had to enable outline-style: auto everywhere first.

The TLDR is that form controls have outline-style: auto by default in the UA style sheet when :-moz-focusring applies. This matches both Blink and WebKit, as far as I can tell.

This is useful because using the auto value allows us to have magic behavior for themed controls that draw their own focus indicators (so as to not draw both a “web” outline and the theme’s outline), while allowing authors to override it, and while displaying the outlines in non-themed form controls.

Improving stylability

My other main goal was to improve stylability and interoperability with other browsers. This one is the one that I hope will bring more joy to web developers :)

Firefox has some, er, interesting behavior with respect to focus indicators, mostly due to the unstyled buttons wanting to look like the native Windows buttons.

These span from the stylable but ugly inner border on buttons (::-moz-focus-inner), from the totally unstylable and un-removable inner focus ring for <select> elements, for which people use terrible hacks to hide.

These indicators were also annoying for users too, specially on Android, where WebKit-based browsers dominate, and web developers don’t usually bother removing them if they don’t want them. The mobile team and users had filed multiple bugs about this.

I believe that we should give web developers a way to style their controls as they please, and that we shouldn’t make web developers go out of their way to get a nice experience on Firefox.

The biggest change here is that un-themed form controls no longer show “inner” focus indicators (like ::-moz-focus-inner). That is, setting -moz-appearance: none (or background, or borders), on your <select> / <button> becomes enough to remove these. This is again something that we could only do after fixing the missing default focus indicators. Now the inner indicator is effectively superseded by the outline.

Another related patch that I plan to land is to make the ::-moz-focus-outer pseudo-element a no-op, using outline instead. This pseudo-element (which only applies to <input type=range>) was a hack to show outlines on non-natively styled <input type=range> by default. The previous work also effectively supersedes it, and allows authors and the implementation to just use outline for it, as one would expect.

Bonus (hopefully): Linux outline changes

This change has still not landed, but I hope the Linux maintainers agree with it, as the behavior matches (to the best of my knowledge) that of GTK.

Firefox’s focus model has two switches, historically, based on platform conventions:

  • Whether focus rings are shown on all focused elements unconditionally. This is true for Linux, dependent on a system setting on Windows (but default false), and false everywhere else. Additionally, once you move the focus using the keyboard on any platform, it becomes true for that window.

  • Whether, if the above switch is false, focus indicators are shown for each element, unless it’s focused via mouse / pointer, and the element is a link, a <video> or an <audio> element. Yeah, that’s the condition, really. This is true for all platforms except Windows.

That means that on Linux you get all the outlines, all the time, regardless of system settings or whether you’ve used the keyboard to navigate the page. This is very annoying, as you get outlines even when clicking links on Google.

My proposal is to align with GTK’s behavior (which also happens to be Windows’ behavior by default). That is, outlines will only show once you’ve navigated by keyboard. You will still be able to go back to the current behavior by toggling the browser.display.show_focus_rings preference back to true in about:config.

Questions? Issues? Follow-up suggestions?

Please test this stuff out on Nightly, and if you disagree with some of the changes / think they’re harmful for either users or developers, or such things, please reach out! Either Bugzilla, email or Twitter works :)