Try to use Tab to advance through focusable elements in a Leaflet map. For example, try with the example map on the Leaflet homepage (https://leafletjs.com/). Elements including the "x" to close the popup, the zoom in ("+") and zoom out ("-") controls, and the bottom-right corner links for "Leaflet" and "OpenStreetMap", will briefly flash the focus ring, but it will then disappear. The element is actually still focused, there is no visible indication. Among other things, this is a nightmare for accessibility.
This seems to be occurring because the Map _handleDOMEvent function calls DomUtil.preventOutline for all mousedown, keypress, keyup, and keydown events. DomUtil.preventOutline is injecting outline: none into the element.style. With the caveat that I am not familiar with this code base, I don't understand this approach. If the desire is to remove the focus ring outline, why wouldn't this be done with CSS on :focus? This would prevent the brief focus ring flash, and it would allow for it to be overridden in CSS (without resorting to !important).
This is a failure of WCAG 2.1 - Success Criterion 2.4.7 Focus Visible.
If outlines are undesirable for some reason, :focus-visible allows for only displaying them on keyboard navigation, which is when it becomes an accessibility issue if they're not displayed to the user.
Is this issue still being looked at? I am also trying to meet accessibility standards while using Leaflet but this has become a major issue.
If you (@akrawitz, @matthoylu, and others) wish to restore the focus outline in your own stylesheet as a quickfix, here's a snippet that should cover most browsers:
.leaflet-container :focus {
outline: -webkit-focus-ring-color auto thin !important; /* Fallback for some browsers that don't support `revert`. */
/* Longhand properties:
outline-color: -webkit-focus-ring-color !important;
outline-style: auto !important;
outline-width: thin !important;
*/
outline: revert !important;
}
In the src, if you replace the handleDOMEvent function to only act on a mousedown event this also can work around the issue.
My understanding is this code is here for drag events, so I assume removing the keyboard events should have minimal impact.
EXISTING:
_handleDOMEvent: function (e) {
if (!this._loaded || skipped(e)) { return; }
var type = e.type;
if (type === 'mousedown' || type === 'keypress' || type === 'keyup' || type === 'keydown') {
// prevents outline when clicking on keyboard-focusable element
preventOutline(e.target || e.srcElement);
}
this._fireDOMEvent(e, type);
},
AFTER CHANGE
_handleDOMEvent: function (e) {
if (!this._loaded || skipped(e)) { return; }
var type = e.type;
if (type === 'mousedown' {
// prevents outline when clicking on keyboard-focusable element
preventOutline(e.target || e.srcElement);
}
this._fireDOMEvent(e, type);
},
Closev via #7259
Most helpful comment
This is a failure of WCAG 2.1 - Success Criterion 2.4.7 Focus Visible.
If outlines are undesirable for some reason,
:focus-visibleallows for only displaying them on keyboard navigation, which is when it becomes an accessibility issue if they're not displayed to the user.