Кратко
СкопированоДиректива @layer, дополнительная функция layer и ключевое слово layer дают вам возможность управлять каскадными слоями.
Каскадные слои — способ группировки и порядок применения стилей в одном источнике. Они помогают браузерам понять, какие стили применить на сайте.
Источник в CSS — место, откуда браузер берёт CSS-правила. Это могут быть ваши стили на сайте, настройки пользователей в браузере и системе, а также браузерные стили по умолчанию. Подробнее об этой и других концепциях в статье «Принцип каскада».
Пример
СкопированоБлагодаря каскадным слоям вы напрямую управляете слоями с разными наборами CSS-правил и решаете, какие стили специфичнее и в каком порядке их применять. Так что они пригодятся для:
- сброса браузерных стилей по умолчанию;
- перезаписи стилей из CSS-фреймворков и библиотек;
- стилизации компонентов;
- хранения стилей в одном месте, например, для состояний интерактивных элементов;
- цветовых тем, схем и поддержки разных режимов передачи цветов.
Например, вот стили с @layer для состояния кнопки при фокусе и когда она неактивна. В слое states устанавливаем стили для :disabled и :focus, а в components — стили кнопки по умолчанию.
@layer components, states;@layer components { .button { display: block; min-width: 210px; border: 2px solid transparent; border-radius: 6px; padding: 9px 15px; color: #000000; font-size: 18px; font-weight: 300; font-family: inherit; transition: background-color 0.2s linear; } .button:hover { background-color: #FFFFFF; cursor: pointer; transition: background-color 0.2s linear; }}@layer states { :focus-visible { border: 2px solid #FFFFFF; outline: none; } :disabled { background-color: #DDDDDD; }}
@layer components, states;
@layer components {
.button {
display: block;
min-width: 210px;
border: 2px solid transparent;
border-radius: 6px;
padding: 9px 15px;
color: #000000;
font-size: 18px;
font-weight: 300;
font-family: inherit;
transition: background-color 0.2s linear;
}
.button:hover {
background-color: #FFFFFF;
cursor: pointer;
transition: background-color 0.2s linear;
}
}
@layer states {
:focus-visible {
border: 2px solid #FFFFFF;
outline: none;
}
:disabled {
background-color: #DDDDDD;
}
}
Без каскадных слоёв нам нужно задать стили классу .button с нужными псевдоклассами. При этом мы не можем хранить их в одном месте файла так, чтобы их случайно не перезаписали другие разработчики.
.button { /* Нужные CSS-правила */}.button:hover { /* Нужные CSS-правила */}.button:focus-visible { /* Нужные CSS-правила */}.button:disabled { /* Нужные CSS-правила */}
.button {
/* Нужные CSS-правила */
}
.button:hover {
/* Нужные CSS-правила */
}
.button:focus-visible {
/* Нужные CSS-правила */
}
.button:disabled {
/* Нужные CSS-правила */
}
С каскадными слоями легче победить сторонние стили. Например, из Bootstrap. Представим, что хотим изменить размер заголовка первого уровня без мучительных поисков нужных Sass-переменных.
<h1 class="fs-1">Последние обновления</h1>
<h1 class="fs-1">Последние обновления</h1>
Стили Bootstrap:
.fs-1 { font-size: 2.5rem !important;}
.fs-1 {
font-size: 2.5rem !important;
}
Наши стили с использованием каскадных слоёв:
@import url("https://cdn.com/bootstrap.min.css") layer;@layer { .fs-1 { font-size: 3rem; }}
@import url("https://cdn.com/bootstrap.min.css") layer;
@layer {
.fs-1 {
font-size: 3rem;
}
}
Со старыми возможностями CSS эту проблему приходится решать несколькими способами. Например, модификатором !important.
.fs-1 { font-size: 3rem !important;}
.fs-1 {
font-size: 3rem !important;
}
Как пишется
СкопированоЕсть несколько способов объявления каскадных слоёв:
- директива
@layer; - ключевое слово
layer; - функция
layer.( )
Слои могут быть с именем (именованными) и без него (анонимными).
С помощью именованных слоёв вы напрямую управляете порядком стилей или определяете его в одном месте CSS-файла.
Анонимные слои не дают другим разработчикам манипулировать правилами в них и гарантируют, что все нужные правила хранятся в одном месте файла. Это особенно полезно, когда заменяете стили из CSS-фреймворка на свои.
После компиляции стилей с каскадными слоями, вы получаете обычный CSS-код. В инструменте разработчика заметите, что ваши стили берутся из файла проекта. Также у правил указано, что это за слой и как называется. Например, «Layer typography» или стили браузера «Layer user agent stylesheet».

Директива @layer
СкопированоДля именованных слоёв укажите имя после директивы @layer, а внутри перечислите нужные правила. Имя слоя может быть любым на латинице. К примеру, application, framework, base, utilities, typography или theme. Имена должны быть уникальными и не повторяться. Исключение — слои, вложенные в другие.
@layer any-layer-name { /* Одно или несколько CSS-правил */}
@layer any-layer-name {
/* Одно или несколько CSS-правил */
}
Слои можно вкладывать друг в друга — группировать. Слой с другими внутри называется родительским, а вложенные в него — дочерними. Обратите внимание, что дочерний слой не может «выйти за пределы» своего родителя. Его не связать с другими дочерними и даже родительскими каскадными слоями.
Здесь слой framework — родительский, а base и theme — дочерние:
@layer framework { @layer base { /* Одно или несколько CSS-правил */ } @layer theme { /* Одно или несколько CSS-правил */ }}
@layer framework {
@layer base {
/* Одно или несколько CSS-правил */
}
@layer theme {
/* Одно или несколько CSS-правил */
}
}
У дочерних слоёв могут быть такие же имена, как у других за пределами его родителя. В этом примере два совершенно разных слоя с именами base и framework, так как второй слой base находится внутри framework:
@layer base { /* Одно или несколько CSS-правил */}@layer framework { @layer base { /* Одно или несколько CSS-правил */ }}
@layer base {
/* Одно или несколько CSS-правил */
}
@layer framework {
@layer base {
/* Одно или несколько CSS-правил */
}
}
Слои можно перечислять в одном месте. Расположите их имена через запятую после директивы @layer. Тут собрали два слоя в одной строке и получили @layer layer.
@layer layer-1, layer-2;@layer layer-1 { /* Одно или несколько CSS-правил */}@layer layer-2 { /* Одно или несколько CSS-правил */}
@layer layer-1, layer-2;
@layer layer-1 {
/* Одно или несколько CSS-правил */
}
@layer layer-2 {
/* Одно или несколько CSS-правил */
}
Когда перечисляете дочерние слои в одну строку, сначала укажите название родительского, а через точку — дочернего. К примеру, у нас есть родительский слой framework и дочерние base и theme. При перечислении имена детей будут framework и framework:
@layer framework.base, framework.theme;@layer framework { @layer base { /* Одно или несколько CSS-правил */ } @layer theme { /* Одно или несколько CSS-правил */ }}
@layer framework.base, framework.theme;
@layer framework {
@layer base {
/* Одно или несколько CSS-правил */
}
@layer theme {
/* Одно или несколько CSS-правил */
}
}
Слои можно перечислять и внутри @layer. В этом случае название слоя снова складывается из имени родителя и ребёнка. Например, в слое framework определяем порядок применения базовых стилей base и стилей для тёмной темы theme. Сами CSS-правила храним в отдельных слоях framework и framework:
@layer framework { @layer base, theme;}@layer framework.base { /* Одно или несколько CSS-правил */}@layer framework.theme { /* Одно или несколько CSS-правил */}
@layer framework {
@layer base, theme;
}
@layer framework.base {
/* Одно или несколько CSS-правил */
}
@layer framework.theme {
/* Одно или несколько CSS-правил */
}
В @layer можно вкладывать и другие директивы. К примеру, @media.
@layer framework { html { color: #000000; background: #FFFFFF; } @media (prefers-color-scheme: dark) { html { color: #FFFFFF; background: #000000; } }}
@layer framework {
html {
color: #000000;
background: #FFFFFF;
}
@media (prefers-color-scheme: dark) {
html {
color: #FFFFFF;
background: #000000;
}
}
}
Для анонимных слоёв указывайте только директиву @layer с нужными правилами внутри.
@layer { /* Одно или несколько правил */}
@layer {
/* Одно или несколько правил */
}
В анонимные слои можно вкладывать именованные. Другие разработчики всё ещё не могут манипулировать стилями в них, так как их родитель остаётся анонимным. Здесь внутри анонимного слоя находятся два дочерних base и typography:
@layer { @layer base { /* Одно или несколько правил */ } @layer typography { /* Одно или несколько правил */ }}
@layer {
@layer base {
/* Одно или несколько правил */
}
@layer typography {
/* Одно или несколько правил */
}
}
Как работает
СкопированоНа то, в каком порядке применяются стили слоёв, влияет порядок их расположения в файле или списке. Также есть особенности поведения CSS-правил и внутри них.
В слое с CSS-правилами и ещё одним @layer выигрывают отдельные правила. В этом примере текст параграфа будет чёрным (#000000), так как селектор с этим правилом за пределами вложенного слоя:
<p class="text--pink"> Неограниченный семиозис симулякров.</p>
<p class="text--pink">
Неограниченный семиозис симулякров.
</p>
@layer typography { /* Я победил 🥇 */ p { color: #000000; } /* Я проиграл */ @layer content;}@layer typography.content { p { color: #FFFFFF; }}
@layer typography {
/* Я победил 🥇 */
p {
color: #000000;
}
/* Я проиграл */
@layer content;
}
@layer typography.content {
p {
color: #FFFFFF;
}
}
Чтобы избежать путаницы, можно всегда выносить такие правила за пределы @layer:
/* Я проиграл */@layer typography { @layer content;}@layer typography.content { p { color: #FFFFFF; }}/* Я победил 🥇 */p { color: #000000;}
/* Я проиграл */
@layer typography {
@layer content;
}
@layer typography.content {
p {
color: #FFFFFF;
}
}
/* Я победил 🥇 */
p {
color: #000000;
}
Когда правила не вложены внутрь @layer, они всегда побеждают. Например, тут текст будет чёрным, несмотря на стили для класса .text в @layer:
<p class="text--pink"> Хроносинкластический инфундибулум.</p>
<p class="text--pink">
Хроносинкластический инфундибулум.
</p>
/* Я проиграл */@layer typography { .text--pink { color: #F498AD; }}/* Я победил 🥇 */p { color: #000000;}
/* Я проиграл */
@layer typography {
.text--pink {
color: #F498AD;
}
}
/* Я победил 🥇 */
p {
color: #000000;
}
Отдельное правило применится даже если расположено выше @layer, так что текст всё ещё чёрный:
/* Я победил 🥇 */p { color: #000000;}/* Я проиграл */@layer typography { .text--pink { color: #F498AD; }}
/* Я победил 🥇 */
p {
color: #000000;
}
/* Я проиграл */
@layer typography {
.text--pink {
color: #F498AD;
}
}
А что, если в слоях есть правила с модификатором !important? В этом случае порядок определяется так:
- Слой с
@layerсо свойством!important, который расположен выше других. - CSS-правило вне
@layer. - Слой с
@layerбез свойств с!important.
Здесь побеждает розовый цвет текста с модификатором !important из слоя typography:
<p class="text--pink"> Мутуализм, комменсализм, паразитизм.</p>
<p class="text--pink">
Мутуализм, комменсализм, паразитизм.
</p>
/* Я победил 🥇 */@layer typography { .text--pink { color: #F498AD !important; }}/* Я проиграл */p { color: #000000 !important;}/* Я тоже проиграл */@layer typography { p { color: #FFFFFF !important; }}
/* Я победил 🥇 */
@layer typography {
.text--pink {
color: #F498AD !important;
}
}
/* Я проиграл */
p {
color: #000000 !important;
}
/* Я тоже проиграл */
@layer typography {
p {
color: #FFFFFF !important;
}
}
Когда перечисляете слои в одну строку, важен их порядок. Первый слой в списке перезаписывается слоем после него и так далее.
В примере текст параграфа <p> снова будет чёрным, так как слой layer находится после layer и поэтому выше в порядке представления:
@layer layer-1, layer-2;/* Я проиграл */@layer layer-1 { p { color: #FFFFFF; }}/* Я победил 🥇 */@layer layer-2 { p { color: #000000; }}
@layer layer-1, layer-2;
/* Я проиграл */
@layer layer-1 {
p {
color: #FFFFFF;
}
}
/* Я победил 🥇 */
@layer layer-2 {
p {
color: #000000;
}
}
Даже если повысить специфичность параграфа из layer с помощью id, layer всё равно победит. Так что текст в параграфе останется чёрным:
@layer layer-1, layer-2;/* Я проиграл */@layer layer-1 { p#light { color: #FFFFFF; }}/* Я победил 🥇 */@layer layer-2 { p { color: #000000; }}
@layer layer-1, layer-2;
/* Я проиграл */
@layer layer-1 {
p#light {
color: #FFFFFF;
}
}
/* Я победил 🥇 */
@layer layer-2 {
p {
color: #000000;
}
}
Перечисление дочерних слоёв в одну строку работает так же. В этом примере есть родитель framework и два ребёнка framework и framework. Текст параграфа снова будет чёрным, так как framework в списке находится после framework:
@layer framework.base, framework.theme;@layer framework { /* Я победил 🥇 */ @layer theme { p { color: #000000; } } /* Я проиграл */ @layer base { p { color: #FFFFFF; } }}
@layer framework.base, framework.theme;
@layer framework {
/* Я победил 🥇 */
@layer theme {
p {
color: #000000;
}
}
/* Я проиграл */
@layer base {
p {
color: #FFFFFF;
}
}
}
Для анонимных слоёв важно, где они находятся в файле. Так что вы не можете добавить их в любое место, как именованные. Ниже анонимный слой расположен перед именованным base, поэтому текст параграфа — чёрный:
/* Я проиграл */@layer { p { color: #FFFFFF; }}/* Я победил 🥇 */@layer base { p { color: #000000; }}
/* Я проиграл */
@layer {
p {
color: #FFFFFF;
}
}
/* Я победил 🥇 */
@layer base {
p {
color: #000000;
}
}
Если расположить анонимный слой после именованного base, текст станет белым (#):
/* Я проиграл */@layer base { p { color: #000000; }}/* Я наконец-то победил 🥇 */@layer { p { color: #FFFFFF; }}
/* Я проиграл */
@layer base {
p {
color: #000000;
}
}
/* Я наконец-то победил 🥇 */
@layer {
p {
color: #FFFFFF;
}
}
Ключевое слово layer
СкопированоКлючевое слово layer нужно, когда применяете правила анонимных слоёв при импорте стилей из другого файла. Это делают с помощью директивы @import.
Укажите слово layer после @import и пути к нужному CSS-файлу. Чтобы другие стили и разработчики точно не перезаписали правила из анонимного слоя, расположите его в самом конце файла. Этот трюк помогает собрать в одном месте самые важные и базовые стили, которые не хотите изменять ни при каких обстоятельствах.
Здесь заменяем нужные стили из файла tailwind.css на стили из анонимного слоя:
@import url(tailwind.css) layer;@layer { /* Одно или несколько правил */}
@import url(tailwind.css) layer;
@layer {
/* Одно или несколько правил */
}
Можете расположить анонимный слой и перед строкой с @import. В этом случае приоритет этих стилей будет ниже, чем у слоёв за ними.
@layer { /* Одно или несколько правил */}@import url(tailwind.css) layer;
@layer {
/* Одно или несколько правил */
}
@import url(tailwind.css) layer;
Правила из одного анонимного слоя можно применять несколько раз. Давайте используем стили из анонимного слоя в файлах base-forms.css, base-links.css и base-buttons.css:
@import url(base-forms.css) layer;@import url(base-links.css) layer;@import url(base-buttons.css) layer;@layer { /* Одно или несколько правил */}
@import url(base-forms.css) layer;
@import url(base-links.css) layer;
@import url(base-buttons.css) layer;
@layer {
/* Одно или несколько правил */
}
Функция layer()
СкопированоС помощью функции layer вы обращаетесь к конкретному слою при импорте стилей из одного файла в другой.
Представим, что нужно добавить свои базовые стили для сайта, на котором уже используем CSS-фреймворк, например, Bootstrap. Создадим слой base с нужными CSS-правилами и применим их в bootstrap.css:
@import url(bootstrap.css) layer(base);@layer base { /* Одно или несколько правил */}
@import url(bootstrap.css) layer(base);
@layer base {
/* Одно или несколько правил */
}
layer даёт повторно использовать стили из одного и того же именованного слоя. Здесь стили из base объединяются с другими из файлов headings.css и links.css:
@import url(buttons.css) layer(base);@import url(links.css) layer(base);@layer base { /* Одно или несколько правил */}
@import url(buttons.css) layer(base);
@import url(links.css) layer(base);
@layer base {
/* Одно или несколько правил */
}
Функция также пригодится, когда нужен определённый дочерний слой внутри анонимного. Представим, что добавляем свои базовые стили для сайта, на котором снова используем Bootstrap. Создадим дочерний слой base внутри анонимного и обратимся прямо к нему с помощью layer:
@import url(bootstrap.css) layer(base);@layer { @layer base { /* Одно или несколько правил */ }}
@import url(bootstrap.css) layer(base);
@layer {
@layer base {
/* Одно или несколько правил */
}
}
Всё вместе
СкопированоДирективу, функцию и ключевое слово можно совмещать. Так вы сможете точнее определить порядок слоёв в одном месте перед объявлением стилей.
В начале файла перечислим слои после @layer. Расположим их так, чтобы у слоя tailwind для перезаписи сторонних стилей был более низкий приоритет, а у application для собственных стилей — самый высокий. На второй строке импортируем стили из tailwind.css и перезапишем нужные слоем tailwind с помощью layer. После этого уже определим нужные нам CSS-правила.
@layer default, tailwind, application;@import url(tailwind.css) layer(tailwind);@layer default { /* Одно или несколько правил */}@layer application { /* Одно или несколько правил */}@layer tailwind { /* Одно или несколько правил */}
@layer default, tailwind, application;
@import url(tailwind.css) layer(tailwind);
@layer default {
/* Одно или несколько правил */
}
@layer application {
/* Одно или несколько правил */
}
@layer tailwind {
/* Одно или несколько правил */
}
@import можно разместить между строками с @layer. Результат будем одинаковым.
@layer default;@import url(tailwind.css) layer(tailwind);@layer application;@layer default { /* Одно или несколько правил */}@layer application { /* Одно или несколько правил */}@layer tailwind { /* Одно или несколько правил */}
@layer default;
@import url(tailwind.css) layer(tailwind);
@layer application;
@layer default {
/* Одно или несколько правил */
}
@layer application {
/* Одно или несколько правил */
}
@layer tailwind {
/* Одно или несколько правил */
}
Если нужно применить несколько слоёв в импортированном файле, перечислите их через запятую на одной строке с @import. Спецификация запрещает импортировать другие файлы после однострочного @layer.
@layer default;@import url(frameworks.css) layer(bootstrap), layer(tailwind);@layer application;@layer default { /* Одно или несколько правил */}@layer application { /* Одно или несколько правил */}@layer bootstrap { /* Одно или несколько правил */}@layer tailwind { /* Одно или несколько правил */}
@layer default;
@import url(frameworks.css) layer(bootstrap), layer(tailwind);
@layer application;
@layer default {
/* Одно или несколько правил */
}
@layer application {
/* Одно или несколько правил */
}
@layer bootstrap {
/* Одно или несколько правил */
}
@layer tailwind {
/* Одно или несколько правил */
}
Как понять
СкопированоКаскадные слои в CSS похожи на слои из редакторов изображений вроде PhotoShop. Для картинок можно добавить несколько слоёв, чтобы гибче управлять разными эффектами и фильтрами. Так как слои прозрачные и не смешиваются друг с другом, легко исправить ошибку или добавить новый эффект без изменения старого.
@layer, layer и layer решают проблемы со стилями без изменения селекторов, а также помогают избежать конфликты между разными слоями из-за их положения в CSS-файлах. Часто эти проблемы появляются из-за нескольких источников стилей. Например, фреймворков и библиотек, которые в основном используют в больших проектах.
- Chrome 99, поддерживается
- Edge 99, поддерживается
- Firefox 97, поддерживается
- Safari 15.4, поддерживается