Функция :where()
помогает писать меньше кода, применять стили ко всему списку и снимает головную боль при использовании CSS reset. В статье разберёмся, как это работает, и посмотрим на примеры использования.
Как пишут на MDN, :where()
— это псевдокласс, который в качестве аргумента принимает список селекторов и применяет заданные стили к любому элементу из этого списка. Полезен, когда надо укоротить длинный список селекторов.
В CSS часто приходится писать длинный список селекторов, разделённых запятыми, когда к нескольким элементам одновременно применяются одни и те же стили.
Вот что бывает, когда один и тот же стиль применим ко всем тегам <a>
внутри header
, main
и footer
.
header a:hover,
main a:hover,
footer a:hover {
color: green;
text-decoratíon: underline;
}
Выше у нас только три элемента. Но когда их больше, код становится трудно читать и понимать. А ещё он визуально становится некрасивым. Вот тут-то и требуется :where()
.
:where(header, main, footer) a:hover {
color: red;
text-decoratíon: underline;
}
Браузер доходит до такого фрагмента кода. Код отправляет его к селекторам header
, main
, и footer
и ко всем якорям в этих селекторах. Когда пользователь наведет курсор на якорь, браузер применит заданный стиль. В этом случае — red
и underline
. То есть список селекторов можно записать коротко и ясно.
С помощью :where()
можно группироваться элементы разными способами. Можно разместить :where()
в начале, середине или в конце селектора. Допустим, у нас есть списки.
/* first list */
header a:hover,
main a:hover,
footer a:hover {
color: green;
text-decoratíon: underline;
}
/* second list */
article header > p,
article footer > p{
color: gray;
}
/* third list */
.dark-theme button,
.dark-theme a,
.dim-theme button,
.dim-theme a{
color: purple;
}
А вот то же самое, сделанное с :where()
.
/* first list */
/* at the beginning */
:where(header, main, footer) a:hover {
color: red;
text-decoratíon: underline;
}
/* second list */
/* in the middle */
article :where(header, footer) > p {
color: gray;
}
/* third list */
/* at the end */
.dark-theme :where(button, a) {
color: purple;
}
В первом списке мы указываем, что red
и underline
должны применяться к header
, main
, и footer
при наведении курсора.
Во втором списке указываем, что содержание, заголовок и футер окрашены в серый.
В третьем списке мы указываем, что для button
и a
задали стили .dark-theme
, .dim-theme
, и purple
.
Упростим ещё.
/* at the end */
.dim-theme :where(button, a) {
color: purple;
}
И ещё.
/* stacked */
:where(.dark-theme, .dim-theme) :where(button, a) {
color: purple;
}
Такой подход к сокращению сложного списка селекторов называется наложением.
Специфичность — способ, с помощью которого браузеры определяют, какие значения свойств CSS или стили нужно применить к конкретному элементу.
Специфичность :where()
всегда равна нулю. Следовательно, любой элемент, на который нацелена функция, автоматически получает равную нулю специфичность. Поэтому можно легко аннулировать стиль любого элемента, сводя специфичность к нулю. Пример с упорядоченными списками HTML.
<div>
<h2>First list no class</h2>
<ol>
<li>List Item 1</li>
<li>List Item 2</li>
</ol>
</div>
<div>
<h2>Second list with class</h2>
<ol class="second-list">
<li>List Item 1</li>
<li>List Item 2</li>
</ol>
</div>
<div>
<h2>Third list with class</h2>
<ol class="third-list">
<li>List Item 1</li>
<li>List Item 2</li>
</ol>
</div>
Во фрагменте кода есть три упорядоченных списка с двумя элементами в каждом. У второго и третьего списка есть заданный класс, у первого — нет. Без применения стилей каждый список упорядочен по номерам.
Добавляем стили. Для этого используем :where()
, чтобы выбрать все теги <ol>
, к которым применен class
.
:where(ol[class]) {
list-style-type: none;
}
Ниже видим, что :where()
применяется ко второму и третьему списку (с классами), поэтому стиль списков удалён.
Добавляем ещё стили.
:where(ol[class]) {
list-style-type: none;
}
.second-list {
list-style-type: disc;
}
Если применять :where()
только ко второму списку, используя наименование класса, то список отобразится с маркерами. А у третьего списка по-прежнему нет стиля.
Вопрос: разве так и не должно быть, раз новый стиль записан ниже :where()
? Нет, и сейчас разберёмся, почему.
Посмотрим, что произойдёт, если переместить добавленный код в верхнюю часть блока кода и передвинуть :where() вниз.
.second-list {
list-style-type: disc;
}
:where(ol[class]) {
list-style-type: none;
}
Стиль всё ещё не изменился.
Запомним, что у :where()
нулевая специфичность. Вне зависимости от того, где размещён новый код относительно :where()
, специфичность элемента, к которому применяется :where()
, равна нулю, а стили аннулированы. Для наглядности давайте добавим стили второго списка в третий список после :where()
в коде.
.second-list {
list-style-type: disc;
}
:where(ol[class]) {
list-style-type: none;
}
.third-list{
list-style-type: disc;
}
Теперь и второй, и третий список отображаются с маркерами, независимо от размещения кода.
Теперь посмотрим, как :where()
будет работать, если один из элементов выбран с помощью недопустимого селектора.
Если браузер в CSS не распознает только один селектор в списке, весь список окажется недопустимым. Стиль не будет применяться. Но только если не использовать :where()
.
Если элемент в :where()
содержит недопустимый селектор, никакой стиль к этому элементу применен не будет. Но для остальных элементов стили сработают. Функция :where()
пропустит недопустимый селектор. Поэтому :where()
называют forgiving-селектором, дословно — «прощающим».
Ниже видим селектор :unsupported
— недопустимый для многих браузеров. Но весь код ниже будет успешно распарсен и будет соответствовать селектору :valid
, даже в браузерах, которые не поддерживают :unsupported
.
:where(:valid, :unsupported) {
...
}
А вот пример кода, который будет проигнорирован в браузерах, которые не поддерживают:unsupported
, но при этом поддерживают селектор :valid
.
:valid, :unsupported {
...
}
Инструмент полезный, но со своими ограничениями. В основном ошибаются из-за нулевой специфичности. Если существует элемент или набор элементов, у которых ни в коем случае не должен поменяться стиль, :where() лучше не использовать. Посмотрим, в каких случаях :where()
нужна и хорошо работает.
Улучшить CSS reset
CSS reset — это загрузка набора правил перед применением любых стилей, чтобы очистить браузер от заданных по умолчанию стилей, и чтобы устранить несоответствия между разными браузерами. CSS reset обычно размещают до собственной таблицы стилей, чтобы эти правила сработали первыми. От сложности или простоты селекторов в CSS reset зависит, насколько трудно будет переопределить исходные стили в коде.
Например, представьте, что мы захотели оформить все якоря на странице зелёным. А потом решили, что в футере все якоря должны быть серыми.
Новый стиль (серый цвет) не применяется из-за особенностей CSS reset. У селектора в CSS reset более высокий порядок специфичности, чем у селектора в коде, который применяет стили только для футера. Но если добавить :where()
в CSS reset, все элементы в CSS reset автоматически приобретут нулевую специфичность. Позже, когда будем менять стили, не надо будет беспокоиться о конфликтах специфичности.
Удалить стили
Функция :where()
помогает удалить или обнулить стили или изменить специфичность элементов. Когда поместим функцию в код, она сработает как reset на минималках.
Минимизировать код
Короткий код легко читать и исправлять. Хороший тон — проверять, можно ли сократить любой код, в котором есть больше двух запятых или больше трёх элементов списка. Эта же стратегия помогает комбинировать два и более селектора: section > header > p > a
.
Функция :where()
помогает работать с CSS resets, удалять стили в любом месте кода и просто делать код красивым и понятным. Пользуетесь?
на главную сниппетов