Spec-Zone.ru › CSS

Представление каскада CSS

Каскад — это алгоритм, определяющий, как пользовательские агенты объединяют значения свойств, полученные из разных источников. Каскад определяет происхождение и уровень, имеющий приоритет, когда объявления из более чем одного источника, слоя каскада или блока источника, слоя каскада или @scope устанавливают значение для свойства элемента.

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

В этой статье объясняется, что такое каскад и в каком порядке CSS объявления каскадируются, охватывая слои каскада и типы происхождения. Понимание приоритета происхождения — ключевой момент для понимания каскада.

Типы происхождения

Задача алгоритма каскада CSS — выбрать объявления CSS для определения правильных значений свойств CSS. Объявления CSS поступают из разных типов происхождения: Стили пользовательского агента, Стили автора и Пользовательские стили.

Хотя таблицы стилей поступают из этих разных источников и могут находиться в разных слоях в каждом из этих источников, они перекрываются по своему объёмному охвату; для работы с этим алгоритм каскада определяет, как они взаимодействуют. Прежде чем обсуждать взаимодействия, мы определим некоторые ключевые термины в следующих разделах.

Стили пользовательского агента

Пользовательские агенты, или браузеры, имеют базовые таблицы стилей, которые предоставляют значения по умолчанию для любого документа. Эти таблицы стилей называются стилями пользовательского агента. Большинство браузеров используют для этой цели фактические таблицы стилей, в то время как другие имитируют их в коде. Конечный результат одинаков.

Некоторые браузеры позволяют пользователям изменять таблицу стилей пользовательского агента, но это редко и не поддаётся контролю.

Хотя некоторые ограничения для таблиц стилей пользовательского агента установлены спецификацией HTML, у браузеров есть значительная свобода: это означает, что некоторые различия существуют между браузерами. Для упрощения процесса разработки веб-разработчики могут использовать таблицу стилей CSS reset, такую как normalize.css, которая устанавливает значения общих свойств в известное состояние для всех браузеров перед началом внесения изменений, соответствующих их конкретным потребностям.

Если таблица стилей пользовательского агента не содержит !important рядом со свойством, делая его «важным», стили, объявленные стилями автора, включая таблицу стилей reset, имеют приоритет над стилями пользовательского агента, независимо от специфичности связанного селектора.

Стили автора

Стили автора — это наиболее распространённый тип таблицы стилей; это стили, написанные веб-разработчиками. Эти стили могут сбрасывать стили пользовательского агента, как указано выше, и определять стили для дизайна данной веб-страницы или приложения. Автор, или веб-разработчик, определяет стили для документа с помощью одной или нескольких связанных или импортированных таблиц стилей, блоков <style> и встроенных стилей, определённых с помощью атрибута style. Эти стили автора определяют внешний вид и ощущения веб-сайта — его тему.

Пользовательские стили

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

Слои каскада

Порядок каскада основан на типе происхождения. Порядок каскада внутри каждого типа происхождения основан на порядке объявления слоёв каскада в этом типе. Для всех источников — пользовательского агента, автора или пользователя — стили могут быть объявлены внутри или вне именованных или анонимных слоев. При объявлении с использованием layer, layer() или @layer стили размещаются в указанном именованном слое или в анонимном слое, если имя не указано. Стили, объявленные вне слоя, обрабатываются как часть анонимного последнего объявленного слоя.

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

Порядок каскадирования

Алгоритм каскадирования определяет, как найти значение для применения к каждому свойству для каждого элемента документа. Следующие шаги относятся к алгоритму каскадирования:

  1. Актуальность: Вначале он фильтрует все правила из разных источников, чтобы оставить только те правила, которые применимы к данному элементу. Это означает, что правила, селекторы которых соответствуют данному элементу и которые являются частью соответствующей media at-команды.

  2. Происхождение и важность: Затем он сортирует эти правила в зависимости от их важности, то есть от того, следуют ли они за !important, и от их происхождения. Игнорируя слои на данный момент, порядок каскада следующий:

    Порядок (низкий к высокому) Происхождение Важность
    1 пользовательский агент (браузер) обычное
    2 пользователь обычное
    3 автор (разработчик) обычное
    4 CSS @keyframe анимации
    5 автор (разработчик) !important
    6 пользователь !important
    7 пользовательский агент (браузер) !important
    8 CSS переходы
  3. Специфичность: В случае равенства с происхождением учитывается специфичность правила для выбора одного значения или другого. Сравниваются специфичности селекторов, и объявление с наивысшей специфичностью выигрывает.

  4. Близость к области действия: Когда два селектора в слое происхождения с приоритетом имеют одинаковую специфичность, значение свойства в правилах области действия с наименьшим числом переходов по DOM-иерархии до корня области действия побеждает. Подробнее см. в разделе Как @scope конфликты разрешаются и пример.

  5. Порядок появления: В источнике с приоритетом, если есть конкурирующие значения для свойства, которые находятся в блоке стилей, соответствующих селекторам с одинаковой специфичностью и близостью области действия, применяется последнее объявление в порядке стилей.

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

Примечание: Переходы и анимации

Значения свойств, установленные анимацией @keyframes, имеют больший приоритет, чем все обычные стили (те, у которых нет !important).

Значения свойств, устанавливаемые в transition, имеют приоритет над всеми другими значениями, даже над теми, которые помечены !important.

Алгоритм каскадирования применяется перед алгоритмом специфичности, что означает, если :root p { color: red;} объявлен в таблице стилей пользователя (строка 2), а менее специфическое p {color: blue;} находится в таблице стилей автора (строка 3), абзацы будут синими.

END_OF_DOCUMENT_MARKER

Базовый пример

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

Здесь у нас есть таблицы стилей пользователя, два таблицы стилей автора и таблица стилей пользователя без встроенных стилей в HTML:

CSS пользователя:

li {
  margin-left: 10px;
}

CSS автора 1:

li {
  margin-left: 0;
} /* This is a reset */

CSS автора 2:

@media screen {
  li {
    margin-left: 3px;
  }
}

@media print {
  li {
    margin-left: 1px;
  }
}

@layer namedLayer {
  li {
    margin-left: 5px;
  }
}

CSS пользователя:

.specific {
  margin-left: 1em;
}

HTML:

<ul>
  <li class="specific">1<sup>st</sup></li>
  <li>2<sup>nd</sup></li>
</ul>

В этом случае объявления внутри правил li и .specific должны применяться.

Еще раз, алгоритм каскадирования состоит из пяти шагов, по порядку:

  1. Релевантность
  2. Происхождение и важность
  3. Специфичность
  4. Близость области применения
  5. Порядок появления

1px предназначен для печати. Из-за отсутствия релевантности на основе типа носителя, он исключается из рассмотрения.

Ни одно объявление не помечено как !important, поэтому порядок приоритета — таблицы стилей автора, затем стили пользователя, затем стили пользователя. Основываясь на происхождении и важности, 1em из таблицы стилей пользователя и 10px из таблицы стилей пользователя исключаются из рассмотрения.

Обратите внимание, что даже если стиль пользователя на .specific 1em имеет более высокую специфичность, это обычное объявление в таблице стилей пользователя. Следовательно, он имеет более низкий приоритет, чем любые стили автора, и удаляется на шаге происхождения и важности алгоритма до того, как даже рассматривается специфичность.

В таблицах стилей автора есть три объявления:

li {
  margin-left: 0;
} /* from author css 1 */
@media screen {
  li {
    margin-left: 3px;
  }
}
@layer namedLayer {
  li {
    margin-left: 5px;
  }
}

Последнее, 5px, — часть слоя каскада. Обычные объявления в слоях имеют меньший приоритет, чем обычные стили, не находящиеся в слое в том же типе происхождения. Это также удаляется на шаге 2 алгоритма, происхождение и важность.

Это оставляет 0 и 3px, которые оба имеют тот же селектор, следовательно, ту же самую специфичность. Ни один из них не находится внутри блока @scope, поэтому близость области применения также не играет роли в этом примере.

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

margin-left: 3px;

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

Стили автора: встроенные стили, слои и приоритет

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

Порядок объявления слоев важен для определения приоритета. Обычные стили в слое имеют приоритет над стилями, объявленными в предыдущих слоях; а обычные стили, объявленные вне любого слоя, имеют приоритет над обычными стилями слоев независимо от специфичности.

В этом примере автор использовал правило CSS @import для импорта пяти внешних таблиц стилей в элемент информации <style>.

<style>
  @import unlayeredStyles.css;
  @import AStyles.css layer(A);
  @import moreUnlayeredStyles.css;
  @import BStyles.css layer(B);
  @import CStyles.css layer(C);
  p {
    color: red;
    padding: 1em !important;
  }
</style>

и затем во внутренности документа у нас есть встроенные стили:

<p style="line-height: 1.6em; text-decoration: overline !important;">Hello</p>

В блоке CSS-кода выше были созданы три слоя каскада с именами «A», «B» и «C» в указанном порядке. Три таблицы стилей были импортированы непосредственно в слои, а две — без создания или назначения слою. «Все неслоистые стили» в списке ниже (нормальный приоритет стиля автора — порядок 4) включают стили из этих двух таблиц стилей и дополнительные неслоистые блоки CSS-стилей. Кроме того, есть два встроенных стиля, обычное объявление line-height и важное объявление text-decoration:

Порядок (с низкого до высокого) Стиль автора Важность
1 A — первый слой обычный
2 B — второй слой обычный
3 C — последний слой обычный
4 Все неслоистые стили обычный
5 встроенный style обычный
6 анимации
7 Все неслоистые стили !important
8 C — последний слой !important
9 B — второй слой !important
10 A — первый слой !important
11 встроенный style !important
12 переходы

Во всех типах происхождения стили, не имеющие важности, содержащиеся в слоях, имеют самый низкий приоритет. В нашем примере обычные стили, связанные с первым объявленным слоем (A), имеют более низкий приоритет, чем обычные стили во втором объявленном слое (B), которые имеют более низкий приоритет, чем обычные стили в третьем объявленном слое (C). Эти стили слоёв имеют более низкий приоритет, чем все обычные неслоистые стили, которые включают обычные стили из unlayeredStyles.css, moreUnlayeredStyles.css, и color p в <style>.

Если какой-либо из стилей слоев A, B или C имеет селекторы с большей специфичностью, соответствующие элементу, подобному :root body p { color: black;}, это не имеет значения. Эти объявления исключаются из рассмотрения из-за происхождения; обычные стили в слоях имеют меньший приоритет, чем обычные неслоистые стили. Однако, если более специфичный селектор :root body p { color: black;} был найден в unlayeredStyles.css, поскольку происхождение и важность имеют одинаковый приоритет, специфичность означала бы, что более специфическое черное объявление выиграет.

Порядок приоритета слоев инвертируется для стилей, объявленных как !important. Важные стили, объявленные в слое, имеют приоритет над важными стилями, объявленными вне слоя. Важные значения, которые появляются в ранних слоях, имеют приоритет над важными стилями, объявленными в последующих слоях каскада.

Встроенные стили

Встроенные стили, объявленные с атрибутом style, относятся только к стилям автора. Обычные встроенные стили имеют приоритет над любыми другими обычными стилями автора, независимо от специфичности селектора. Если line-height: 2; был объявлен в блоке селектора :root body p в любой из пяти импортированных таблиц стилей, высота строки по-прежнему была бы 1.6.

Обычные встроенные стили имеют приоритет над другими обычными стилями автора, если свойство не изменяется анимацией CSS.

Все важные встроенные стили имеют приоритет над всеми стилями автора, важными и неважными, встроенными и не встроенными, слоистыми и неслоистыми. Важные стили также имеют приоритет над анимированными свойствами, но не над переходами. Три вещи могут переопределить важный встроенный стиль: 1) важный стиль пользователя, 2) важный стиль пользователя или 3) значение свойства, которое переходит.

Важность и слои

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

Например, следующий CSS:

p {
  color: red;
}
@layer B {
  :root p {
    color: blue;
  }
}

Несмотря на то, что красный объявлен первым и имеет менее специфический селектор, потому что неслоистый CSS имеет приоритет над слоистым CSS, абзац будет красным. Если бы мы включили встроенный стиль в абзац, устанавливающий другой цвет, например <p style="color: black">, абзац был бы черным.

Когда мы добавим !important в этот фрагмент CSS, порядок приоритета меняется с таблицей стилей:

p {
  color: red !important;
}
@layer B {
  :root p {
    color: blue !important;
  }
}

Теперь абзац будет синим. !important в самом раннем объявленном слое имеет приоритет над последующими слоями и неслоистыми важными объявлениями. Если встроенный стиль содержал !важно, например, <p style="color: black !important">, опять же абзац был бы черным. Встроенная важность имеет приоритет над всеми другими объявленными !important объявлениями, независимо от специфичности.

Примечание: Флаг !important меняет порядок приоритета слоев каскада. По этой причине старайтесь не использовать !important для переопределения внешних стилей. Вместо этого используйте @import вместе с ключевым словом layer или функцией layer() для импорта внешних таблиц стилей (из фреймворков, стилей виджетов, библиотек и т. д.) в слои. Импорт таблиц стилей в слой в качестве первого объявления в вашем CSS понижает их приоритет, а определенные автором слои, определенные позже в вашем CSS, будут иметь более высокий приоритет. Флаг !important следует использовать с осторожностью, если вообще использовать, для защиты необходимых стилей от последующих переопределений, в первом объявленном слое.

Стиль перехода имеет приоритет над всеми важными стилями, независимо от того, кто или как они объявлены.

END_OF_DOCUMENT_MARKER

Полный порядок каскадирования

Теперь, когда у нас есть более глубокое понимание типа источника и приоритета слоя каскадирования, мы понимаем, что таблицу в Порядке каскадирования было бы точнее представить следующей таблицей:

Порядок приоритета
(от низкого к высокому)
Источник стилей Важность
1 user-agent — первый объявленный слой нормальная
user-agent — последний объявленный слой
user-agent — стили без слоёв
2 пользователь — первый объявленный слой нормальная
пользователь — последний объявленный слой
пользователь — стили без слоёв
3 автор — первый объявленный слой нормальная
автор — последний объявленный слой
автор — стили без слоёв
встроенные style
4 анимации
5 автор — стили без слоёв !important
автор — последний объявленный слой
автор — первый объявленный слой
встроенные style
6 пользователь — стили без слоёв !important
пользователь — последний объявленный слой
пользователь — первый объявленный слой
7 user-agent — стили без слоёв !important
user-agent — последний объявленный слой
user-agent — первый объявленный слой
8 переходы

Какие сущности CSS участвуют в каскадировании

В каскадировании участвуют только объявления пар свойство/значение CSS. Описатели правил CSS @-правил не участвуют в каскадировании, а атрибуты представления HTML не являются частью каскадирования.

Правила @

Правила CSS @-правил, содержащие сущности, отличные от объявлений, такие как правило @font-face, содержащее описатели, не участвуют в каскадировании.

В основном, свойства и описатели, определённые в @-правилах, не участвуют в каскадировании. В каскадировании участвуют только @-правила в целом. Например, в рамках правила @font-face имена шрифтов определяются с помощью описателей font-family. Если определены несколько правил @font-face с одним и тем же описателем, учитывается только наиболее подходящее @font-face, как единое целое. Если несколько правил одинаково подходят, все объявления @font-face сравниваются, используя шаги 1, 2 и 4 алгоритма (специфичности в отношении @-правил нет).

Хотя объявления, содержащиеся в большинстве @-правил, таких как те, что в @media, @document или @supports, участвуют в каскадировании, само @-правило может сделать весь селектор нерелевантным, как мы видели со стилями печати в основном примере.

Объявления в @keyframes не участвуют в каскадировании. Как и в случае с @font-face, только всё @keyframes в целом выбирается алгоритмом каскадирования. Порядок приоритета анимаций описан ниже, в разделе анимации CSS и каскад.

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

Наконец, @charset подчиняется специфическим алгоритмам и не затрагивается алгоритмом каскадирования.

Атрибуты представления

Атрибуты представления — это атрибуты в исходном документе, которые могут влиять на стили. Например, устаревший атрибут align при включении устанавливает выравнивание на нескольких HTML-элементах, а атрибут fill определяет цвет, используемый для рисования фигур и текста SVG, и определяет конечное состояние SVG-анимаций. Хотя они являются стилями автора, атрибуты представления не участвуют в каскадировании.

Если атрибут представления HTML поддерживается пользовательским агентом, допустимые атрибуты представления, включённые в HTML и SVG, такие как атрибуты align или fill, переводятся в соответствующие правила CSS (все атрибуты представления SVG поддерживаются как свойства CSS) и вставляются в стиле авторского листа перед любыми другими стилями со специфичностью, равной 0.

Атрибуты представления не могут быть объявлены !important.

Анимации CSS и каскад

Анимации CSS, использующие правила @keyframes, определяют анимации между состояниями. Ключевые кадры не каскадируются, что означает, что в любой момент времени CSS берёт значения только из одного @keyframes, и никогда не смешивает несколько.

Если несколько анимаций ключевых кадров определены с тем же именем анимации, последний определённый @keyframes в источнике и слое с наибольшим приоритетом. Используется только одно определение @keyframes, даже если @keyframes анимируют разные свойства. @keyframes с одинаковым именем никогда не объединяются.

p {
  animation: infinite 5s alternate repeatedName;
}
@keyframes repeatedName {
  from {
    font-size: 1rem;
  }
  to {
    font-size: 3rem;
  }
}

@layer A {
  @keyframes repeatedName {
    from {
      background-color: yellow;
    }
    to {
      background-color: orange;
    }
  }
}
@layer B {
  @keyframes repeatedName {
    from {
      color: white;
    }
    to {
      color: black;
    }
  }
}

В этом примере есть три отдельные объявления анимаций с именем repeatedName. При применении animation: infinite 5s alternate repeatedName к абзацу применяется только одна анимация: анимация ключевых кадров, определённая в CSS без слоёв, имеет приоритет над объявлениями анимации ключевых кадров в слоях, исходя из порядка приоритета источника и слоя каскадирования. В этом примере будет анимироваться только размер шрифта элемента.

Примечание: Анимаций с важностью нет, поскольку объявления свойств в блоке @keyframes, которые содержат !important в качестве части значения, игнорируются.

Сброс стилей

После того, как ваш контент завершил изменение стилей, он может оказаться в ситуации, когда ему нужно восстановить их до известного состояния. Это может произойти в случаях с анимациями, изменениями темы и так далее. Свойство CSS all позволяет быстро установить (почти) всё в CSS обратно в известное состояние.

all позволяет вам выбрать немедленное восстановление всех свойств до любого из их начальных (по умолчанию) состояний, состояния, унаследованного от предыдущего уровня каскада, конкретного источника (листа стилей пользовательского агента, листа стилей автора или листа стилей пользователя) или даже очистки значений свойств полностью.

Спецификации

Спецификация
CSS Cascading and Inheritance Level 4

См. также

  • Основы: каскад CSS
  • Основы: слои каскада
  • Модуль каскада и наследования CSS
  • Синтаксис CSS
  • Специфичность
  • Наследование
  • Правила @
  • Начальное, вычисленное, используемое и фактическое значения

© 2005–2024 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/CSS/Cascade

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API