ДокументацияCSSCSS Nesting: вложенные правила без препроцессора
Начальный 6 мин чтения

CSS Nesting: вложенные правила без препроцессора

Вложенные CSS-правила (Nesting) — нативная вложенность без Sass, синтаксис &, вложенные media queries, правила и сравнение с препроцессорами.

CSS nestingвложенные стиливложенность CSSнативный nestingCSS

Что такое CSS Nesting

Раньше для вложенности нужен был Sass/LESS. Теперь CSS поддерживает вложенность нативно:

.card {
  background: white;
  border-radius: 12px;
  padding: 1rem;

  .title {
    font-size: 1.25rem;
    font-weight: 700;
  }

  .body {
    color: #6b7280;
  }

  &:hover {
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);
  }
}

Компилируется в:

.card { background: white; border-radius: 12px; padding: 1rem; }
.card .title { font-size: 1.25rem; font-weight: 700; }
.card .body { color: #6b7280; }
.card:hover { box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1); }

Синтаксис & (амперсанд)

& — ссылка на родительский селектор:

.button {
  background: #6366f1;
  color: white;

  &:hover {
    background: #4f46e5;
  }

  &:active {
    transform: scale(0.98);
  }

  &:focus-visible {
    outline: 2px solid #6366f1;
    outline-offset: 2px;
  }

  &.primary {
    background: #6366f1;
  }

  &.secondary {
    background: #e5e7eb;
    color: #374151;
  }
}

& не только в начале

.card {
  /* ... */

  .wrapper & {
    /* .wrapper .card */
    margin: 0;
  }

  body.dark & {
    /* body.dark .card */
    background: #1f2937;
    color: white;
  }
}

Вложенные media queries

Media queries можно вкладывать прямо в правило:

.container {
  width: 100%;
  padding: 1rem;

  @media (min-width: 768px) {
    width: 750px;
    padding: 2rem;
  }

  @media (min-width: 1024px) {
    width: 980px;
  }
}

Это удобнее, чем выносить media query отдельно для каждого компонента.

Другие at-правила

.card {
  @supports (backdrop-filter: blur(12px)) {
    backdrop-filter: blur(12px);
    background: rgba(255, 255, 255, 0.1);
  }

  @container (min-width: 400px) {
    grid-template-columns: 1fr 2fr;
  }
}

Глубина вложенности

Технически — неограниченная. Практически — не вкладывайте глубже 3 уровней:

/* OK */
.card {
  .title { }
  .body { }
}

/* Уже сомнительно */
.card {
  .header {
    .title { }
    .subtitle { }
  }
}

/* Слишком глубоко — рефакторите */
.card {
  .header {
    .title {
      .icon {
        svg { }
      }
    }
  }
}

Порядок вложенных правил

Вложенные правила могут идти вперемешку с объявлениями:

.card {
  background: white;   /* объявление */

  .title { }           /* вложенное правило */

  padding: 1rem;       /* ещё объявление — работает */

  .body { }            /* ещё правило */
}

Сравнение с Sass

/* Нативный CSS */
.nav {
  display: flex;
  gap: 8px;

  a {
    color: #6366f1;

    &:hover {
      text-decoration: underline;
    }
  }
}

/* Sass — то же самое */
.nav {
  display: flex;
  gap: 8px;

  a {
    color: #6366f1;

    &:hover {
      text-decoration: underline;
    }
  }
}

Синтаксис идентичен. Если вы переходите с Sass, менять ничего не нужно.

Что Sass умеет, а CSS нет: переменные с $, @mixin/@include, @extend, @function, математические операции +, -. Нативный CSS заменяет @mixin через кастомные свойства и @layer.

Когда использовать

  • В компонентных CSS-файлах — группировка стилей одного компонента
  • Вместо Sass для новых проектов — меньше зависимостей
  • В <style> Vue-компонентов — уже работает
<style scoped>
.card {
  border-radius: 12px;
  overflow: hidden;

  img {
    width: 100%;
    height: 200px;
    object-fit: cover;
  }

  .content {
    padding: 1rem;
  }

  &:hover {
    box-shadow: 0 4px 16px rgba(0,0,0,0.1);
  }
}
</style>

Поддержка

CSS Nesting поддерживается во всех современных браузерах с 2023 года. Для старых браузеров используйте PostCSS-плагин postcss-nesting или Sass в качестве полифилла.

Итог

  • Нативная вложенность — без Sass, LESS и других препроцессоров
  • & — ссылка на родительский селектор
  • Media queries вкладываются прямо в правило
  • Не вкладывайте глубже 3 уровней
  • Поддержка во всех современных браузерах