Что такое вложенность CSS?

0 Акции
0
0
0
0

Введение

Если вы фронтенд-разработчик, работавший с препроцессором CSS, вы, вероятно, сталкивались или использовали функцию вложенности. Это популярная функция, и для меня она стала одной из тех, что побудила меня использовать препроцессор CSS.

В этом году поддержка вложенности CSS появилась во всех основных браузерах: Chrome, Firefox и Safari. Это ключевая функция CSS, упрощающая написание CSS-кода. В этой статье я расскажу о том, что я узнал о вложенности CSS, и поделюсь своими выводами, а также примерами использования.

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

Вложенность в CSS — долгожданная функция для многих разработчиков. Раньше мы полагались на препроцессоры CSS, такие как Sass или Less. Позвольте мне кратко рассказать о них:

Рассмотрим следующий пример. У нас есть иконка, которая находится в селекторе .nav__item.

.nav__item {
.icon {
display: flex;
padding: 1rem;
}
}

Приведённый выше код является допустимым кодом Sass. После компиляции в браузере он будет выглядеть следующим образом:

.nav__item .icon {
display: flex;
padding: 1rem;
}

При использовании встроенной функции вложенности CSS тот же самый CSS будет работать как есть. На рисунке показано сравнение встроенной функции вложенности CSS и инструментов разработчика браузера.

Обратите внимание, как браузер отображает CSS почти так же, как он отображается в CSS.

Если бы этот CSS-код был скомпилирован в Sass, браузер отобразил бы его следующим образом:

Преимущества вложенности CSS

На мой взгляд, существуют веские причины, по которым вложенные CSS-стили полезны:

  • CSS легче читать.
  • Группировка стилей
  • Ограничение определенных стилей
  • Стилизация HTML-элементов, не имеющих классов или идентификаторов.

Правила вложенности CSS

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

Прежде всего, вам нужно узнать о символе амперсанда (&). Существует ряд ситуаций, когда этот символ необходим.

Вложенность элемента без класса или идентификатора

В этом примере элемент <a> Оформление осуществляется с помощью `.nav__item`. Использование тега `&lt;head&gt;` необязательно для корректной работы CSS.

.nav__item {
  & a {
    display: block;
    padding: 1.5rem 1rem;
  }
}

/* Same as: */
.nav__item a {
}

Вы также можете отказаться от проставления галочки:

.nav__item {
a {
display: block;
padding: 1.5rem 1rem;
}
}
/* Same as: */
.nav__item a {
}

Обратите внимание, что это недавнее обновление, и оно называется «Расслабленная вложенность CSS». Оно работает в последних версиях Chrome Canary и Safari Technology Preview. Ознакомьтесь с этой статьей об «Расслабленной вложенности» от Адама Аргила.

Вложенность элемента с классом

Рассмотрим тот же пример, что и раньше, но предположим, что элемент <a> В нём есть HTML-класс.

.nav__item {
.link {
display: block;
padding: 1.5rem 1rem;
}
}
/* Same as: */
.nav__item .link {
}

Здесь нет необходимости использовать символ. Имя класса подойдет идеально.

Вложенные CSS-комбинаторы

Одним из преимуществ нативной вложенности CSS является использование комбинаторов. Давайте рассмотрим несколько примеров.

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

В стандартной CSS-вложенности мы можем использовать символ амперсанда, чтобы имитировать его. Обратите внимание, что я повторил его дважды.

.nav__item {
& + & {
border-left: 2px solid;
}
}

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

Еще один пример вложенности — это комбинатор дочерних элементов. Он может выбирать непосредственного потомка элемента.

.nav__item {
> a {
padding: 1rem;
}
}

Символ амперсанда

.nav__item {
& a {
color: blue;
}
}

Это было необходимо в первоначальной спецификации вложенности CSS. В Safari TP 179+ и Chrome Canary 120 амперсанд больше не требуется для вложенных элементов.

В результате работает следующее:

.nav__item {
a {
color: blue;
}
}

Единственная проблема заключается в том, что вам придётся вернуться к предыдущей версии спецификации, которая должна включать разметку и соответствующие ей документы.

Вложенность с примером: Active, Focus, Hover

:active, :focus и :hover — это псевдоклассы CSS, которые активируются действиями пользователя.

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

button {
&:hover {
background-color: var(--bg-color);
}
&:focus {
outline: solid 2px;
}
}

Разница при использовании препроцессора для вложенности заключается в том, что браузер отображает её следующим образом:

button:hover {
background-color: var(--bg-color);
}
button:focus {
outline: solid 2px;
}

Давайте посмотрим, как вложенность CSS отображается в Chrome, Safari и Firefox.

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

Пример вложенной структуры: публикация контента

Один из первых примеров тестирования вложенных CSS-стилей — это оформление основного содержимого публикации. Представьте себе статью с заголовками, текстом, изображениями, цитатами и многим другим.

Заголовки

Мы обычно оформляем заголовки следующим образом:

.post-content h1,
.post-content h2,
.post-content h3,
.post-content h4 {
/* styles here */
}

С помощью вложенных CSS-стилей это проще:

.post-content {
h1,
h2,
h3,
h4 {
color: var(--heading-color);
font-weight: var(--heading-font-bold);
margin-bottom: var(--size-2);
}
}

То же самое можно сделать и с помощью селектора :is().

.post-content {
:is(h1, h2, h3, h4) {
color: var(--heading-color);
font-weight: var(--heading-font-bold);
margin-bottom: var(--size-2);
}
}

Элемент абзаца

Распространенный пример — оформление ссылки, находящейся внутри абзаца. В таком случае вложенность CSS-стилей работает отлично.

.post-content {
& p {
color: var(--color-black);
& a {
font-weight: bold;
text-decoration: underline;
}
}
}

Для отображения ссылки также может потребоваться эффект наведения курсора или фокусировки.

.post-content {
& p {
color: var(--color-black);
& a {
font-weight: bold;
text-decoration: underline;
&:hover {
/* hover styles */
}
}
}
}

Мы также можем вкладывать медиа-запросы друг в друга.

.post-content {
& p {
/* base styles */
@media (min-width: 400px) {
/* do something */
}
}
}

В некоторых случаях CMS может быть элементом <p> Оберните его в другой элемент, и в целях стиля его следует использовать только для прямых элементов. <p> Создайте стиль.

.post-content {
/* Select the direct <p> elements */
> p {
/* base styles */
}
}

Блочная цитата

В этом примере цитата получает собственный стиль и элемент <p> Внутри цитаты выберите параметр, чтобы сбросить нижнее поле до нуля.

.post-content {
& blockquote {
/* custom quote styling */
& p {
margin-bottom: 0;
}
}
}

Форма столба

Форма для отправки сообщения содержит изображение и

Отображение описания изображения необязательно.

В моем примере, если

У объекта есть заголовок, и мне нужно изменить его стиль. Это можно сделать с помощью CSS-стиля `:has()`.

.post-content {
& figure {
& img {
/* the figure's image styles */
}
/* changes to the <figure> container, if it has a figcaption element */
&:has(figcaption) {
display: flex;
align-items: start;
}
& figcaption {
/* caption styling */
}
}
}

Список сообщений

Мне нужно добавить рамку ко всем элементам списка, кроме последнего. Для этого я использовал селектор :not().

.post-content {
li {
&:not(:last-child) {
border-bottom: 1px solid;
}
}
}

Чтобы использовать `:not()`, необходимо добавить перед ним амперсанд.

Настраиваемое расстояние для заголовков

Следующее расстояние должно быть <h3> и <h4> Я уменьшу количество символов, если за одним из них последует фрагмент кода.

.post-content {
& h3 + [class*="language-"],
& h4 + [class*="language-"] {
margin-top: 0.5rem;
}
}

Как вы убедились на этом практическом примере, использование вложенности CSS очень просто, особенно если вы знакомы с препроцессорами CSS.

Вложенность на примере: компонент Card

Я покажу простой компонент карточки, который использует вложенность CSS для достижения желаемых стилей.

Предположим, что существует элемент `.card` со стилями по умолчанию или базовыми стилями. Я продемонстрирую использование вложенных CSS-стилей.

.card {
/* default card styles */
}

ЗАПРОСЫ ПО КОНТЕЙНЕРАМ ДЛЯ ГНЕЗДАНИИ

Если ширина контейнера превышает 400 пикселей, я хочу, чтобы карточка трансформировалась в гибкий контейнер.

.card {
/* default card styles */
/* if the container width is 400px or bigger */
@container card (min-width: 400px) {
display: flex;
}
}

Оформление элемента абзаца

Я хочу использовать элемент абзаца следующим образом: <h3> Таким образом, я могу задать поля и отступы для элемента. <p> Добавлю. Если этого не будет, то и в пользовательском интерфейсе не будет дополнительного пространства.

.card__content {
& h3 + p {
border-top: 1px solid #000;
padding-top: 0.5rem;
margin-top: 0.5rem;
}
}

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

.card__content {
& h3 + p {
border-top: 1px solid #000;
padding-top: 0.5rem;
margin-top: 0.5rem;
}
@container card (min-width: 400px) {
display: flex;
flex-direction: column;
justify-content: center;
}
}

Вложенность на примере: поле ввода формы

Распространенный случай — оформление заполнителя поля ввода. Проблема в том, что у каждого производителя браузеров свой префикс (ой, на дворе 2023 год).

Поскольку для префиксных стилей требуется двоеточие, необходимо использовать символ &, иначе стили не будут работать.

input {
--placeholder-color: #969696;
/* other styles */
&::-webkit-input-placeholder {
color: var(--placeholder-color);
}
&::-moz-placeholder {
color: var(--placeholder-color);
opacity: 1;
}
&:-moz-placeholder {
color: var(--placeholder-color);
}
}

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

/********** Option 1: native nesting **********/
input {
&::-webkit-input-placeholder {
color: var(--placeholder-color);
}
}
/********** Option 2: without nesting **********/
input::-webkit-input-placeholder {
color: var(--placeholder-color);
}

Между ними нет никакой разницы. Оба обладают одинаковыми свойствами (0, 1, 1).

Вложенность с примером: стилизация элемента через его родительский элемент.

Мы можем использовать вложенность CSS для изменения стилей дочернего элемента в зависимости от его местоположения. Например, если элемент `.button` находится внутри родительского элемента `.box`, он должен занимать всю ширину.

<div class="box">
<h2>Get access to all features</h2>
<p>Create an account now and get access to all exclusive features.</p>
<a href="/offer" class="button">Create an account</a>
</div>
.button {
.box & {
width: 100%;
}
}
/* equivalent to */
.box .button {
}

Ошибки, которые я обнаружил при изучении вложенности CSS.

Использование беззнакового глобального селектора

Допустим, у нас есть карточка, и мы хотим выделить все элементы внутри неё. С помощью CSS Native Nesting это должно сработать:

.card {
* {
/* styles here */
}
}

Я заметил, что это не работает в Chrome Stable, но прекрасно функционирует в Chrome Canary 121, Safari 17.1 и Firefox 119.

Решение состоит в добавлении знака препинания.

.card {
& * {
/* styles here */
}
}

Использование беззнаковых атрибутов данных

В данном случае выбор атрибута данных без галочки не дает ожидаемого результата.

.card {
[data-type="featured"] {
/* styles here */
}
}

Я заметил, что это не работает в Chrome Stable, но прекрасно функционирует в Chrome Canary 121, Safari 17.1 и Firefox 119.

Чтобы это исправить, нужно добавить запятую:

.card {
&[data-type="featured"] {
/* styles here */
}
}

Обе эти ошибки были исправлены в версии Chrome Canary, обеспечивающей более свободную вложенность CSS.

Определение поддержки вложенности CSS

Параметр `@supports` можно использовать для проверки поддержки вложенности CSS-стилей. В нашем случае мы хотим проверить, распознает ли браузер амперсанд.

@supports selector(&) {
.post-content {
& h2 {
/* styles here. */
}
}
}

Другие варианты определения поддержки можно посмотреть в этом примере на Codepen от Bramus.

Сегодня я воспользуюсь плагином PostCSS nesting, который компилирует вложенный CSS в обычный CSS. Я удалю этот плагин, когда его использование станет безопасным.

Инструменты разработчика для UX-вложенности CSS

Мне не очень нравится текущий пользовательский интерфейс для вложенных CSS-кодов в инструментах разработчика браузера.

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

Результат

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Вам также может понравиться