Removing list styles removes list semantics in iOS

October 20, 2021

Say you’re on a navigation element. You might do something like this in HTML:

<ul class="nav">
  <li class="nav__item"> ... </li>
  <li class="nav__item"> ... </li>
  <li class="nav__item"> ... </li>
</ul>

And when styling it, you probably want to strip out the bullet points in CSS:

.nav li {
  list-style: none;
}

Then you move right along with your merry day.

The only problem is that wipes out the semantics of the list in VoiceOver in WebKit browsers. With list styling, VoiceOver announces the list and the number of items in it. Without list styling, VoiceOver only announces the content in the list items.

This came up while I was editing an interview with Elad Shechter about his “New CSS Reset” where he discusses his decision to include list-style: none; in the reset:

If we choose not to reset list-style, it means we can’t use list elements for navigation. This also means that we won’t get any semantics for any other browsers.

And now, if I need to choose between most browsers gaining these semantics, and no browsers gaining these semantics, I’m choosing the former, as more browsers gain from it than they lose.

—Elad Shechter, “The New CSS Reset”

I honestly have no super strong opinion on the way browsers handle semantics in this situation. I care more that they’re handling semantics consistently so I’m not making false assumptions or researching cross-browser behavior on every style declaration in my CSS.

But it’s good to know. And, funny enough, this came up almost immediately after when I was editing another article that uses list elements to create an expandable grid. In it, Kev Bonett says:

I still believe that using a <ul><li> construct for the grid is a suitable approach for a list of product cards. The afforded semantics indicate an explicit relationship between the cards.

—Ken Bonett, “Expandable Sections Within a CSS Grid”

That does set up a bit of a battle ground in the brains of front-end developers. We’re aiming for semantics but sometimes have to make a choice that’s based on the “greater good” rather than true cross-platform support.

This also reminds me of a trick that uses “pseudo-commas” to create inline lists. Maybe semantics need to be expanded to consider that sort of use case as well? We have <ul>, <ol>, and <dl><il> anyone?