Главная » Статьи » Руководство по новым современным селекторам псевдоклассов CSS

Руководство по новым современным селекторам псевдоклассов CSS

Руководство по новым современным селекторам псевдоклассов CSS

От автора: проект редактора рабочей группы CSS для селекторов уровня 4 включает несколько селекторов псевдо-классов, которые уже включены в большинство современных браузеров. В этом руководстве будут рассмотрены те из них, которые в настоящее время лучше всего поддерживаются, а также приведены примеры, демонстрирующие, как вы можете начать их использовать!

Селекторы псевдокласса — это те селекторы, которые начинаются с символа двоеточия «:» и соответствуют состоянию текущего элемента. Состояние может быть относительно дерева документа или указывать на изменение состояния, например :hover или :checked.

:any-link

Хотя этот псевдо-класс определен в уровне селекторов 4, он уже довольно давно поддерживается разными браузерами. Псевдо-класс any-link будет соответствовать гиперссылке, если она содержит href. Он будет равен значению, эквивалентному сопоставлению обоих и :link и :visited. По сути, это может уменьшить ваши стили на один селектор, если вы добавляете базовые свойства, такие как color, которые хотите применить ко всем ссылкам, независимо от их статуса посещения.

:any-link { color: blue; text-underline-offset: 0.05em;
}

Важное замечание о специфичности состоит в том, что селектор :any-link будет более приоритетным чем a, поскольку он имеет специфику класса. В следующем примере ссылки будут фиолетовыми:

:any-link { color: purple;
} a { color: red;
}

Поэтому, если вы используете :any-link, помните, что вам нужно будет включить его в экземпляры селектора a, если они будут напрямую конкурировать за уникальность.

:focus-visible

Могу поспорить, что одним из наиболее распространенных нарушений доступности в Интернете является удаление outline для состояния :focus, для интерактивных элементов таких как ссылки, кнопки и входные данные формы. Одна из основных целей outline — служить визуальным индикатором для пользователей, которые в основном используют клавиатуру для навигации. Состояние видимого фокуса имеет решающее значение , поскольку когда пользователи кликают по интерфейсу — это помогает усилить фокусироку на интерактивном элементе. В частности, видимый фокус описан критерием WCAG 2.4.11: Внешний вид фокуса.

Псевдо-класс :focus-visible предназначен чтоб показать область фокусировки, в том случае, когда агент пользователя определяет с помощью эвристики, что она должна быть видна. Другими словами: браузеры будут определять, когда применять :focus-visible на основе таких вещей, как метод ввода, тип элемента и контекст взаимодействия. В целях тестирования с помощью настольного компьютера с вводом с клавиатуры и мыши вы должны видеть стили :focus-visible, при переходе к интерактивному элементу, но не при клику по нему, за исключением ввода текста и текстовых полей, которые должны отображать :focus-visible для всех типов ввода фокуса.

Примечание. Для получения дополнительных сведений ознакомьтесь с рабочим проектом :focus-visible.

Последние версии браузеров Firefox и Chromium, теперь обрабатывают входные данные формы :focus-visible в соответствии со спецификацией, в которой говорится, что UA должен удалять стили :focus при совпадении с :focus-visible. Safari еще не поддерживает функцию :focus-visible поэтому нам нужно убедиться, что стиль :focus включен в качестве запасного варианта, чтобы избежать ошибок доступности при удалении outline.

Давайте посмотрим, что получится при наличии кнопки и поля ввода текста со следующим набором стилей:

input:focus,
button:focus { outline: 2px solid blue; outline-offset: 0.25em;
} input:focus-visible { outline: 2px solid transparent; border-color: blue;
} button:focus:not(:focus-visible) { outline: none;
} button:focus-visible { outline: 2px solid transparent; box-shadow: 0 0 0 2px #fff, 0 0 0 4px blue;
}

Chrome и Firefox

input. Правильно удаляют стили :focus, когда элементы выделены фокусом с помощью ввода мыши, в пользу :focus-visible в результате изменений border-color и скрытия outline ввода с клавиатуры.

button. Не только используют :focus-visible без дополнительного правила для button:focus:not (:focus-visible) что удалит outline с :focus, но и обеспечивают видимость box-shadow только при вводе с клавиатуры.

Safari

input. Продолжает использовать только стили :focus.

button. Частично поддерживает :focus-visible на кнопке, скрывая стили :focus по клику, но все еще отображая стили :focus при взаимодействие с клавиатуры.

Так что на данный момент рекомендуется продолжать использовать стили :focus, а затем прогрессивно улучшать их использованием :focus-visible. Вот CodePen, на котором вы можете тестировать:

:focus-within

Псевдо-класс :focus-within имеет поддержку среди всех современных браузеров, и действует почти как родительский селектор, но только для очень специфических условий. При присоединении к содержащему элементу и соответствию дочернему элементу стили :focus могут быть добавлены к содержащему элементу и / или любым другим элементам в контейнере.

Практическое усовершенствование для использования этого поведения — стилизация формы, когда связанное поле ввода выделено фокусом. Чтобы это работало, мы оборачиваем форму и поле в контейнер, а затем прикрепляем :focus-within к этому контейнеру:

.form-group:focus-within label { color: blue;
}

Это приводит к тому, что метка становится синей, когда вход находится в фокусе. Эта демонстрация CodePen также включает добавление схемы непосредственно в контейнер .form-group:

:is()

Также известный как псевдокласс «соответствует любому», :is() может принимать список селекторов, с которыми нужно сопоставить. Например, вместо того, чтобы перечислять стили заголовков по отдельности, вы можете сгруппировать их с помощью селектора :is(h1, h2, h3).

Пара уникальных особенностей списка селекторов :is():

Если указанный селектор недействителен, правило будет по-прежнему соответствовать допустимым селекторам. Напимер правило :is(-ua-invalid, article, p) будет соответствовать article и p.

Специфичность элемента будет равна специфичности переданного селектора с наивысшей специфичностью. Например, :is(#id, p) будет иметь специфичность #id- 1.0.0 — тогда как :is(p, a) будет иметь специфичность 0.0.1.

Первое поведение, заключающееся в игнорировании недопустимых селекторов, является ключевым преимуществом. При использовании нескольких селекторов в группе, где один селектор недействителен, браузер отбросит целое правило. Это применяется в некоторых случаях, когда префиксы поставщика по-прежнему необходимы, а группировка селекторов с префиксом и без префикса приводит к сбою во всех браузерах. С помощью :is() вы можете безопасно сгруппировать эти стили, и они будут применяться, когда они совпадают, и игнорироваться, когда нет.

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

:is(h1, h2, h3) { line-height: 1.2;
} :is(h2, h3):not(:first-child) { margin-top: 2em;
}

В этом примере (который взят из стилей документов в моем проекте SmolCSS) наличие line-heightу наследованного от базовых стилей, или его отсутствие margin-top не является проблемой для не поддерживающих браузеров. То, что вы пока не хотели бы использовать, так это важные стили макета, такие как Grid или Flex, которые существенно контролируют интерфейс.

Кроме того, при привязке к другому селектору вы можете проверить, совпадает ли базовый селектор с дочерним селектором внутри :is(). Например, следующее правило выбирает только абзацы, которые являются прямыми потомками статей. Универсальный селектор используется как ссылка на базовый селектор p.

p:is(article > *)

Для лучшей поддержки, если вы хотите начать ее использовать, вы также можете удвоить стили , включив повторяющиеся правила с помощью :-webkit-any() и :matches(). Не забудьте установить эти индивидуальные правила, иначе браузер их проигнорирует! Другими словами, включите следующее:

:matches(h1, h2, h3) { } :-webkit-any(h1, h2, h3) { } :is(h1, h2, h3) { }

Здесь стоит упомянуть, что наряду с новыми селекторами есть обновленная версия @supports, которая является @supports selector, а также и @supports not selector.

Вы можете проверить поддержку :is() с помощью следующего кода, но на самом деле вы не сможете использовать это в Safari, поскольку Safari поддерживает :is(), но не поддерживает @supports selector.

@supports selector(:is(h1)) { :is(h1, h2, h3) { line-height: 1.1; }
}

:where()

Псевдокласс :where() почти идентичен :is(), за исключением одного критического отличия: он всегда будет иметь нулевую специфичность. Это имеет невероятные последствия для людей, создающих фреймворки, темы и дизайн-системы. Используя :where(), автор может установить значения по умолчанию, а последующие разработчики могут включать переопределения или расширения без противоречий в специфике.

Рассмотрим следующий набор стилей img. При использовании :where() даже с селектором с более высокой специфичностью специфичность остается нулевой. Как вы думаете, какой цвет рамки будет у изображения в следующем примере?

:where(article img:not(:first-child)) { border: 5px solid red;
} :where(article) img { border: 5px solid green;
} img { border: 5px solid orange;
}

Первое правило не имеет никакой специфичности, поскольку полностью содержится внутри :where(). Таким образом, против второго правила побеждает второе. Введя селектор img только для элементов в качестве последнего правила, он будет приоритетнее благодаря каскаду. Это потому, что у него будет та же специфичность, что и :where(article) img, поскольку :where() не увеличивает специфичность.

Использование :where() вместе с запасными вариантами немного сложнее из-за функции нулевой специфичности, поскольку эта функция, вероятно, является причиной, по которой вы захотите использовать :is() повторно . И если вы добавите резервные правила, они, вероятно, будут лучше в силу самой своей природы :where(). И у него лучшая общая поддержка, чем у @supports selector. В принципе, помните о невозможности правильно создать резервные копии :where() и внимательно проверьте свои данные, чтобы определить, безопасно ли начинать использовать :where() для вашей аудитории.

Вы можете продолжить тестирование :where() с помощью следующего CodePen, в котором используются указанные выше селекторы:

:not()

Базовый селектор :not() поддерживается начиная с Internet Explorer 9. Но «Селекторы уровня 4» усовершенствовали :not(), позволяя принимать список селекторов :is() и :where(). Следующие правила обеспечивают тот же результат при поддержке браузера:

article :not(h2):not(h3):not(h4) { margin-bottom: 1.5em;
} article :not(h2, h3, h4) { margin-bottom: 1.5em;
}

Способность :not() принимать список селекторов отлично поддерживается современными браузерами. Как мы видели, расширенный :not() также может содержать ссылку на базовый селектор в качестве потомка с использованием *. Пример на CodePen демонстрирует эту способность, выбирая ссылки, которые не являются потомками nav.

:has()

Последний псевдокласс, который является очень интересным предложением, но не имеет текущей реализации ни в одном браузере, даже экспериментальным способом — :has(). Фактически, он внесен в черновик редакции секторов уровня уровня 4 как «подверженный риску», что означает, что :has() связан с трудностями внедрения, и поэтому его могут исключить из рекомендаций.

Если бы он был реализован, он, по сути, был бы «родительским селектором», который многие специалисты по CSS стремились бы использовать. Он будет работать с логикой, аналогичной комбинации и :focus-within и :is() с дочерними селекторами, где вы ищете наличие потомков, но примененный стиль будет относиться к родительскому элементу.

Согласно следующему правилу, если бы навигация содержала кнопку, то верхний и нижний отступы навигации уменьшились бы:

nav { padding: 0.75rem 0.25rem; nav:has(button) { padding-top: 0.25rem; padding-bottom: 0.25rem;
}

Опять же, в настоящее время это не реализовано ни в одном браузере даже экспериментально — но об этом нужно задуматься!

:empty

Полезный псевдо-класс, который вы, возможно, пропустили в уровне селекторов 3 — это :empty, который соответствует элементу, когда у него нет дочерних элементов, включая текстовые узлы. Правило p:empty будет применяться к <p></p>, но не применяться к <p>Hello</p>.

Один из способов, которым вы можете использовать :empty, это скрыть элементы, которые, возможно, являются заполнителями для динамического содержимого, которое заполняется с помощью JavaScript. Возможно, у вас есть div, который будет получать результаты поиска, и когда он будет заполнен, у него будет граница и некоторые отступы. Но пока результатов нет, вы не хотите, чтобы он занимал место на странице. Используя :empty вы можете скрыть этот div с помощью:

.search-results:empty { display: none;
}

Вы можете подумать о добавлении сообщения в пустое состояние и у вас возникнет соблазн добавить его с помощью псевдоэлемента content. Проблема здесь в том, что сообщения могут быть недоступны для пользователей вспомогательных технологий, которые не соответствуют тому, есть ли у них доступ к content. Другими словами, чтобы убедиться, что сообщение типа «нет результатов» доступно , вам нужно добавить его как реальный элемент, например абзац.

РЕСУРСЫ ДЛЯ ИЗУЧЕНИЯ СЕЛЕКТОРОВ

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

Документация по селекторам CSS MDN включает исчерпывающий список категорий;

Получайте удовольствие от изучения CSS-селекторов с игрой CSS Diner;

Китти Джираудель создала инструмент объяснения селекторов, который разбивает и описывает части предоставленного селектора.

Автор: Stephanie Eckles

Источник: www.smashingmagazine.com

Редакция: Команда webformyself.

Читайте нас в Telegram, VK, Яндекс.Дзен