От декларации до отображения

Sofi Valitova, CSS-engineer

Валитова София

От декларации
до отображения

🇫🇮🏊🏻‍🧊🎌
:root { color: yellow;}div { color: 40px;}.class { color: gold !important;}#id { color: 1ms;}@keyframes color {  from { color: fuchsia; }  to { color: tomato; }}:has(.class, #id) {   color: purple !important;}* { animation: color 2s infinite; }
=>🪄=>
CSS

Поплыли!

Value processing

  1. Declared value
  2. Cascaded value
  3. Specified value
  4. Computed value
  5. Used Value
  6. Actual Value

Declared value

Список всех значений, подходящих этому элементу.

  • Селектор
  • Условия
  • Проверка типа

Declared value

Список всех значений, подходящих этому элементу.

  • Селектор
  • Условия
  • Проверка типа

Селектор

<div class="a">CSS</div><style>  #id { /* ... */ }  .a { /* ... */ }  div { /* ... */ }</style>

Declared value

Сбор всех деклараций свойства, применимых к элементу

  • Селектор
  • Условия
  • Проверка типа

Условия

<div class="a">Safari IOs</div><style>  @media (max-width: 600px) {}  @supports (display: flex) {}  @media (min-width: 1200px) {}</style>

Declared value

Сбор всех деклараций свойства, применимых к элементу

  • Селектор
  • Условия
  • Проверка типа

Проверка типа

<div class="a">CSS</div><style>  .a {    height: 12ms;    height: 12em;  }</style>

Короткие свойства (shorthand) 🦖

Короткие свойства (shorthand) 🦖

background: url('image.svg');

то же самое, что:

background-image: url('image.svg');background-color: initial;background-origin: initial;....

Выбрали декларации

свойствозначениеселекторместо
border-left-colorred#abccssWritingModes.html:12
border-left-stylesolid#idstyle.css:14
height10px-style attribute
colorgreen[attr='value']style.css:6
border-left-colorred.astyle.css:123

Cascading
Style
Sheets

Что такое каскад?

Cascaded value

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

Cascaded value

  • Уровни объявления
  • Слои @layer
  • Специфичность селекторов
  • Порядок объявления

Уровни объявления

Декларации из Transition
!important декларации user-агента
!important декларации пользователя
!important декларации автора (то есть разработчика)
Animation декларации
Декларации автора (то есть разработчика)
Декларации пользователя
Декларации user-агента

Уровни объявления

Декларации из Transitiontransition
!important декларации user-агента! user-agent
!important декларации пользователя! user
!important декларации автора (то есть разработчика)! author
Animation декларацииanimation
Декларации автора (то есть разработчика)author
Декларации пользователяuser
Декларации user-агентаuser-agent

Декларации user-агента

  • transition
  • ! user-agent
  • ! user
  • ! author
  • animation
  • author
  • user
  • user-agent

Декларации user-агента

  • transition
  • ! user-agent
  • ! user
  • ! author
  • animation
  • author
  • user
  • user-agent

Декларации автора

  • transition
  • ! user-agent
  • ! user
  • ! author
  • animation
  • author
  • user
  • user-agent
.blue {    color: blue;}.red {    color: red;}
CSS

Декларации автора

  • transition
  • ! user-agent
  • ! user
  • ! author
  • animation
  • author
  • user
  • user-agent
.blue {    color: blue;}.red {    color: red !important;}
CSS

Декларации анимаций

  • transition
  • ! user-agent
  • ! user
  • ! author
  • animation
  • author
  • user
  • user-agent
.blue {    color: red;    animation: anim 3s infinite;}@keyframes anim {    50% {color: green;}}
CSS

Декларации анимаций

  • transition
  • ! user-agent
  • ! user
  • ! author
  • animation
  • author
  • user
  • user-agent
.blue {    color: red !important;    animation: anim 3s infinite;}@keyframes anim {    50% {color: green;}}
CSS

Декларации переходов

  • transition
  • ! user-agent
  • ! user
  • ! author
  • animation
  • author
  • user
  • user-agent
.red {    color: red;    transition: color 1s;}.green    color: green;}
CSS

Декларации переходов

  • transition
  • ! user-agent
  • ! user
  • ! author
  • animation
  • author
  • user
  • user-agent
.red {    color: red;    transition: color 1s;}.green    color: green !important;}
CSS

Декларации пользователя

Уровни объявления

Декларации из Transition
!important декларации user-агента
!important декларации пользователя
!important декларации автора (то есть разработчика)
Animation декларации
Декларации автора (то есть разработчика)
Декларации пользователя
Декларации user-агента

История

Декларации анимаций в 2020

.blue {    color: red !important;    animation: anim 3s infinite;}@keyframes anim {    50% {color: green;}}
CSS

Выводы из истории:

Не молчите
о проблеме

Cascaded value

  • Уровни объявления
  • Слои @layer
  • Специфичность селекторов
  • Порядок объявления

Слои @layer

Способ создать уровни объявления внутри стилей автора.

@layer default, components, theme;@layer default {   button {  color: red; }}@import url('theme.css') layer(theme); }@layer components {   button { color: green; }}

А что, если у нас две декларации на одном уровне?

Две декларации на одном уровне?

<div class="red" id="blue">     CSS</div><style>  #blue { color: blue; }  .red { color: red; }</style>

Две декларации на одном уровне?

<div class="red" id="blue">     CSS</div><style>  #blue { color: blue !important; }  .red { color: red !important; }</style>

Здесь нет конфликта селекторов

  • transition
  • ! user-agent
  • ! user
  • ! author
  • animation
  • author
  • user
  • user-agent
<div class="red" id="blue">     CSS</div><style>  .red { color: red !important; }  #id { color: blue; }</style>

Коэффициент специфичности

Набор чисел, позволяющий определить приоритет селектора.

  • как разряды в числе
  • как семантическое версионирование

Коэффициент специфичности

Селектора делятся на 3 уровня:

#id+100
.class, :hover,[name="value"]0+10
::before, div00+1

Коэффициент специфичности

Селектора делятся на 3 уровня:

#id1 * 1000 * 100 * 1100
.class, :hover,[name="value"]0 * 1001 * 100 * 1010
::before, div0 * 1000 * 101 * 1001

Коэффициент специфичности

span0 * 1000 * 101 * 1001
.class #id1 * 1001 * 100 * 1110
.class #id::before:hover1 * 1002 * 101 * 1121
#id [name="value"]1 * 1001 * 100 * 1110

Коэффициент специфичности

А минусы где?

Сравним 11 классов и один идентификатор:

#id = 1 * 10^2 + 0 * 10^1 + 0 * 10^0 = 100

.a.b.c.d.e.f.e.r.g.t.h =
= 0 * 10^2 + 11 * 10^1 + 0 * 10^0 = 110

что же
такое?????

11 классов больше идентификатора???

На самом деле чуть-чуть не так

Используется степень двойки.

1 * 10^2 + 1 * 10^1 + 1 * 10^0

1 * 2^24 + 1 * 2^16 + 1 * 2^8

Семантическое версионирование

1major.0minor.2patch

Коэффициент специфичности

селекторmajorminorpatchрезультат
span0010.0.1
.class #id1111.1.0
.class #id::before:hover1211.2.1
#id [name="value"]1101.1.0

Коэффициент специфичности

селекторmajorminorpatchрезультат
#id1001.0.0
.a.b.c.d.e.f.e.r.g.t.h01100.11.0

polypane.app/css-specificity-calculator/

Атрибут style

Считается специфичнее всего для целей этого этапа.

<div id="id" style="color:red">CSS</div><style>  #id { color: blue; }<style>

Порядок объявления

А что, если у нас два селектора одной специфичности?

<div class="red blue">CSS</div><style>  .blue { color: blue; }  .red { color: red; }</style>

Порядок объявления

Чем ближе к концу документа, тем приоритетнее

<div class="red blue">CSS</div><style>  .blue { color: blue; }  .red { color: red; }</style>

Выбрали одну декларацию

свойствозначениеселекторместо
height100px#abcindex.html:12
height10em#idstyle.css:14
heightcalc(50% - 25px)-style=""
height50%[n='4']style.css:6
height1vh.astyle.css:123

Specified value

А что, если свойство не указали ни мы, ни юзер-агент?

Specified value

А что, если свойство не указали ни мы, ни юзер-агент?

Берем initial value

Теперь у свойства точно есть значение

Computed value

Значение, которое наследуется.

height: 100px; // => 100px
height: inherit // => 100px 
font-size: 10px;
height: 5em; // => 50px CV=50px 
font-size: 20px;height: inherit; // => 50px  CV=50px  

Computed value

  1. Вычисляются зависимые величины.
height: 100px; // => 100px
height: 50%; // => 50px CV = 50%
height: inherit; // => 25px CV = 50% 

Computed value

  1. Вычисляются зависимые величины. Кроме процентов!
--h: 100px;
height: var(--h); // => 100px  CV=100px 
--h: 10px;height: inherit; // => 100px  CV=100px  

Computed value

  1. Проценты не вычисляются. Но остальные зависимые величины вычисляются.
  2. Подставляются переменные.

После этого этапа у нас есть значение, в котором посчитано все, что можно посчитать без отрисовки документа.

Used value

Считаем проценты

height: 50%;     /* CV = 50% */    /* UV = 25px */

Считаем calc()

width: calc(100px - 50%);     /* CV = calc(100px - 50%) */    /* UV = 25px */

Немного про calc()

width: calc(-50px); width: calc(2s); width: calc(50% - 50px); 
width: 100px; // => 100px
width: calc(50% - 25px);  // => UV = 25px
width: inherit; // => -12.5px ??? 

Range Checking (Проверка диапазона)

Приводим к ближайшему допустимому.

width: 100px; // => 100px
width: calc(50% - 25px); // => UV = 25px
width: inherit; // => 0px 

Считаем calc-size()

height: calc-size(auto, size - 50%);    /* CV = calc-size(auto, size - 50%) */    /* UV = 25px */

Справка про calc-size()

calc-size( <calc-size-basis>, <calc-sum> )
  1. Базис
  2. Выражение для вычисления

Справка про calc-size()

width: calc-size(max-content, size / 2);

Actual value

Преобразования на основе ограничений среды.

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

Один слайд, чтобы править всеми

  • Отбираем декларации
  • Выбираем одну
  • Наследуем её
  • Вычисляем
  • Отрисовываем на устройстве

Источники

София Валитова из KiskoLabs

Презентация сделана с помощью Shower.