In September of 2017 Gerard K. Cohen of Unfettered Thoughts posted an article on the how VoiceOver and Safari (Webkit) (macOS and iOS) remove list element semantics when
list-style: none is used. It’s not just using
list-style: none, but any CSS that would remove the bullet or number indicators of a list’s items will also remove the semantics.
This isn’t the only instance of CSS modifying how elements are exposed to assistive technologies, such as screen readers. Modifying
visibility to “none” or “hidden”, respectively, will not only visually hide content, but remove the elements from being exposed to accessibility APIs. However, where those properties will consistently hide and show content to all browsers and screen reader pairings, this example of changing the list style is unique to Safari/Webkit.
Why is Webkit the only browser engine that behaves this way?
When a bug is a feature is a bug?
In March of 2017, a bug was filed about
list-style: none affecting exposed list semantics. Eventually, it prompted the response:
This was a purposeful change due to rampant “list”-itis by web developers. … Basically, if you remove all default visible indication of the list, there is no indication to a sighted user or screen reader user that the content is a list. If you want to override this heuristic for accessibility, you can always add an explicit ARIA role=”list”.
I can understand this reasoning. Semantics are hard and people do misuse HTML kinda a lot, always and forever. The counter point here though is that there are legitimate scenarios where one might want to remove the default styling of a list, but still have it be exposed as a list. Especially if that list is restyled in a way where it still visually looks like a list.
It is unfortunate that the best solution to this issue will defy the first rule of Using ARIA, which states:
If you can use a native HTML element or attribute with the semantics and behavior you require already built in, instead of re-purposing an element and adding an ARIA role, state or property to make it accessible, then do so.
Another excerpt from Using ARIA:
None of the elements defined in HTML4 need ARIA roles added to expose their default semantics. … In the majority of cases setting an ARIA role and/or aria-* attribute that matches the default implicit ARIA semantics is unnecessary and not recommended as these properties are already set by the browser.
It is a constant struggle educating developers new to accessibility, that they “don’t need to use ARIA attributes if they’ve used appropriate HTML elements.” As situations like this then require caveats:
“Except you do need to use ARIA to re-attach list semantics for this one specific browser and screen reader combination.
No you don’t need to do this for other browsers and screen reader combos.
No, this doesn’t happen with Chrome (Blink) and VoiceOver.
No, you’ll just have to ignore the warnings your automated checkers give you that say ‘don’t double up ARIA roles on their native element equivalents’.
No, this ‘fix’ isn’t necessary for Internet Explorer…”
With that said, sometimes you have to go against best practices when best practices don’t align with what it is you need to accomplish.
A fix for the fix
Previously (prior to this post being updated in November 2019), this section outlined some hacks you could do with CSS
::before pseudo elements to force Webkit to re-instate list semantics when their list markers were removed.
Since the original Unfettered Thoughts article and this post were written, some things have changed with the way the CSS hacks were impacting how VoiceOver announced lists that contained only static text content.
Due to these changes, and not wanting to promote hacks which could result in less than ideal user experiences, the solutions have been removed.
A more suitable, and straight forward, way to re-add list semantics (if even necessary) would be to do the following:
<ul role="list"> <!-- add the list role to the <ul> --> <li>...</li> <li>...</li> <li>...</li> <!-- etc. --> </ul>
As Adrian Roselli notes on Twitter a lack of list semantics “…may not be a big deal unless user testing says you really need a list.” While this behavior can be unwelcome in some situations, let’s also not spend too much effort over correcting an over correction which was in response to an over use of unnecessary semantics.
Perform testing with real people!
I find myself a bit torn here. The decision to remove list semantics if a list is no longer styled to look like a list does make sense… Typically I think it’s important for elements to look like what they are. But a blanket decision like this can get into some opinionated territory. It also discounts the fact that there are other ways to visually interpret lists than just if they have default list markers, such as bullets. So, while I understand the decision, I don’t agree fully agree with Webkit’s approach.
It goes too far in the other direction, and it breaks form with how other browsers expose, and screen readers interpret, styled lists. Developers don’t typically expect CSS to affect the semantics of HTML. However, that’s something maybe people should start thinking more about.
Especially when you take into consideration things I talked about in my post Unbuttoning Buttons, and Adrian Roselli goes over in his articles Display: Contents Is Not a CSS Reset and Tables, CSS Display Properties, and ARIA. CSS can have some damaging affects on the way HTML elements are exposed to the browser’s accessibility API, and developers can be none the wiser to them.
Just check out the many responses, retweets and likes to Sara Soueidan’s tweet:
#TIL that removing list bullets with `list-style: none` removes <ul/ol> semantics in VoiceOver.— Sara Soueidan (@SaraSoueidan) January 11, 2019
Adding zero-width space fixes this; so this is yet another thing to add to our base #CSS files. #a11y https://t.co/NOpyZneSYc
via @scottohara @rogerjohansson
There were many front-end devs and even those who are focused specifically on accessibility who unaware of this behavior in Safari.
As Eric Eggert exclaims:
We really need an open conversation on what CSS is allowed to overwrite semantics. Apart from display:none/visibility:hidden, I personally think no CSS should alter the semantics of the page.— Eric Eggert (@yatil) January 11, 2019
and as James Craig responds to the above mentioned thread:
This decision was all about the users’ experience on the majority of pages where web developers are not paying attention to the screen reader experience. Definitely open to change suggestions (including updating the heuristic) that make it better for authors w/o penalizing users.— James Craig (@cookiecrook) January 12, 2019
So, feedback is welcome :)