Семантические горизонтальные списки

Источник: «Semantic inline lists»
Иногда требуется, чтобы список отображался не вертикально, а в виде горизонтального списка (как в навигационном меню).
<ul class="list-inline">
<li>Merlin</li>
<li>Ursula</li>
<li>Radagast</li>
</ul>

Для этого обычно устанавливают стиль list-style на none, а затем каким-либо образом (с помощью Flexbox или margins) стилизуют элементы списка с помощью отступов.

.list-inline {
list-style: none;
margin-left: 0;

/* В этом подходе используется flexbox */
display: flex;
align-items: center;
column-gap: 1em;
flex-wrap: wrap;

}

/*
В качестве альтернативы можно стилизовать сами элементы списка
Это не требуется, если вы используете flexbox
*/

.list-inline li {
display: inline-block;
}

.list-inline li:not(:last-child) {
margin-right: 1em;
}

Но… в Safari семантика списка удаляется при использовании list-style: none.

Иногда это имеет смысл, но иногда нет. Если использовать в качестве примера навигационный список, то в нем, вероятно, следует использовать семантику списка.

Исторически сложилось два способа решения этой проблемы. Можно добавить к элементу атрибут [role="list"].

<ul class="list-inline" role="list">
<li>Merlin</li>
<li>Ursula</li>
<li>Radagast</li>
</ul>

Это восстанавливает семантику списка, но также является дополнительным атрибутом для каждого элемента, с которым вы хотите использовать класс. Кроме того, вы можете забыть это сделать.

Раньше существовал ещё один CSS-хак на, разработанный Скоттом О'Харой, избавляющий вас от необходимости добавлять роль к каждому элементу, но Scott рекомендует больше не использовать его.

Ранее (до обновления этого поста в ноябре 2019 года) в этом разделе описывались хаки, которые можно было сделать с использованием псевдоэлементов CSS ::before, чтобы заставить Webkit восстановить семантику списка после удаления его маркеров.

Со времён написания первоначальной статьи Unfettered Thoughts и этой заметки кое-что изменилось в том, как CSS-хаки воздействовали на то, как VoiceOver объявлял списки, содержащие только статическое текстовое содержимое.

В связи с этими изменениями, а также не желая поощрять хаки, способные привести к не самым лучшим последствиям для пользователей, эти решения были удалены.

Это то, что я использовал в течение многих лет (на основе статьи Скотта). И похоже, что я должен удалить это со всех своих сайтов.

Однако на этой неделе Мануэль Матузович обнаружил, что использование list-style-type: "" с пустой строкой вместо list-style: none позволяет добиться того же результата без семантических последствий.

.list-inline {
list-style-type: "";
margin-left: 0;

/* Этот подход использует flexbox */
display: flex;
align-items: center;
column-gap: 1em;
flex-wrap: wrap;

}

Но, как отметил Скотт в своей оригинальной статье…

CSS может оказывать разрушительное воздействие на способ передачи HTML-элементов в API доступности браузера, причём разработчики могут об этом даже не догадываться.

Я не уверен, что это правильный шаг, но он, безусловно, более удобен для разработчиков.

Скотт также отмечает…

Были внесены дополнительные изменения в то, как Safari отображает семантику списков в зависимости от контекста их вложенности. Например, если список является потомком элемента <nav>, то даже если стили списка удалены, Safari/VoiceOver будет отображать его для пользователей как список…

Как отмечает Адриан Розелли в Twitter, отсутствие семантики списка …может не иметь большого значения, если только пользовательское тестирование не покажет, что вам действительно нужен список. Хотя такое поведение в некоторых ситуациях может быть нежелательным, давайте не будем тратить слишком много усилий на исправление ошибок, которые были сделаны в ответ на чрезмерное использование ненужной семантики.

То есть, возможно, имеет смысл либо просто обернуть горизонтальные списки в nav, либо вообще не беспокоиться об этом.

Дополнительные материалы

Предыдущая Статья

Веб-производительность и параллельная vs. waterfall загрузка

Следующая Статья

Вышел PHP 8.3 с типизированными константами классов, функцией json_validate и многим другим