Шпаргалка собирает то, что приходится вспоминать чаще всего: селекторы и расчёт специфичности (ID-CLASS-TYPE), единицы rem, em, %, vw, dvh, ch и функцию clamp(), box-sizing и позиционирование, свойства Flexbox и Grid, переменные, медиа- и контейнерные запросы и рецепты центрирования. Каждый фрагмент кода проверен в браузере, а статус поддержки новых возможностей дан по Baseline на дату проверки.
После материала вы сможете
- посчитать специфичность селектора, включая
:is(),:where()и:has(), и понять, какое правило победит - выбрать единицу (
rem,em,%,dvh,ch) и задать гибкий размер черезclamp() - найти свойство Flexbox или Grid под задачу и отцентрировать блок одним из проверенных рецептов
Что знать заранее
Проверено на
Microsoft Edge 155 + Playwright 1.64web-features 3.42 (Baseline)
Сверено с документацией: 12 октября 2026 г.
Содержание
Селекторы: от простых до :is(), :where() и :has()
Селектор говорит браузеру, к каким элементам применить правило. Комбинаторы (пробел, >, +, ~) связывают селекторы по положению в дереве документа, псевдоклассы (:hover) описывают состояние, псевдоэлементы (::before) — часть элемента, которой нет в HTML.
*
- Что выбирает
- все элементы
- Пример
* { margin: 0; }
p
- Что выбирает
- элементы по тегу
- Пример
p { line-height: 1.6; }
.card
- Что выбирает
- элементы с классом
- Пример
.card { padding: 16px; }
#app
- Что выбирает
- элемент с
id - Пример
#app { min-height: 100dvh; }
[type="email"]
- Что выбирает
- по атрибуту и значению
- Пример
input[type="email"]
A B
- Что выбирает
Bгде угодно внутриA- Пример
nav a
A > B
- Что выбирает
B— прямой потомокA- Пример
ul > li
A + B
- Что выбирает
Bсразу послеA- Пример
h2 + p
A ~ B
- Что выбирает
- все
BпослеAна одном уровне - Пример
h2 ~ p
:hover, :focus-visible
- Что выбирает
- состояние элемента
- Пример
a:hover,button:focus-visible
:nth-child(2n)
- Что выбирает
- по номеру среди соседей
- Пример
tr:nth-child(2n)
::before, ::after
- Что выбирает
- псевдоэлемент до или после содержимого
- Пример
.req::after { content: "*"; }
:is(A, B)
- Что выбирает
- любой из списка; вес — самого тяжёлого аргумента
- Пример
:is(h1, h2) a
:where(A, B)
- Что выбирает
- то же, но с весом 0
- Пример
:where(ul, ol) li
:not(A)
- Что выбирает
- всё, что не подходит под
A - Пример
li:not(:last-child)
A:has(B)
- Что выбирает
A, внутри или рядом с которым естьB- Пример
.card:has(img)
:has() впервые позволил выбрать родителя или предыдущий элемент по тому, что идёт дальше. Три типовых приёма — раскладка карточки по наличию картинки, подсветка подписи у незаполненного поля и «неактивная» кнопка формы с ошибками:
/* Карточка с картинкой — в две колонки, без картинки — как обычно */
.card:has(img) {
display: grid;
grid-template-columns: 120px 1fr;
gap: 16px;
}
/* Подпись над незаполненным обязательным полем */
label:has(+ input:invalid) {
color: crimson;
}
/* Кнопка отправки тускнеет, пока в форме есть ошибки */
form:has(:invalid) button[type="submit"] {
opacity: 0.5;
}display: grid только у карточки с <img>, подпись crimson и кнопка с opacity: 0.5, пока обязательное поле пустое; после ввода — обычный вид.Специфичность: как посчитать вес селектора
Когда несколько правил задают одно свойство, браузер сравнивает специфичность — три числа ID-CLASS-TYPE. Сравнение идёт слева направо: один ID сильнее любого числа классов. При равном весе побеждает правило, которое стоит ниже. Специфичность сравнивается только внутри одного источника и слоя каскада.
*
- Вес
- 0-0-0
- Почему
- универсальный селектор веса не добавляет
ul li
- Вес
- 0-0-2
- Почему
- два тега; комбинаторы не считаются
.item, [type="email"], :hover
- Вес
- 0-1-0
- Почему
- класс, атрибут и псевдокласс — в одной колонке
li.item
- Вес
- 0-1-1
- Почему
- класс + тег
a::before
- Вес
- 0-0-2
- Почему
- псевдоэлемент считается как тег
#nav .item
- Вес
- 1-1-0
- Почему
- ID побеждает даже 11 классов
:not(.active)
- Вес
- 0-1-0
- Почему
- сам
:not()без веса, считается аргумент
:is(#nav, .menu) li
- Вес
- 1-0-1
- Почему
- берётся самый тяжёлый аргумент, даже если совпал
.menu
:where(#nav) li
- Вес
- 0-0-1
- Почему
:where()всегда 0
style="…"
- Вес
- выше любого селектора
- Почему
- перебивается только
!important
nav a { color: gray; } /* 0-0-2 */
.menu a { color: black; } /* 0-1-1 — сильнее */
:where(.menu) a { color: red; } /* 0-0-1 — :where() не добавляет веса */
:is(.menu, #top) a { color: blue; } /* 1-0-1 — вес самого «тяжёлого» аргумента */<nav class="menu"><a>. В Edge 155 ссылка синяя: :is(.menu, #top) получил вес ID, хотя #top на странице нет. Без последней строки — чёрная.- Порядок решения конфликта: важность (
!important) и источник → слой@layer→ специфичность → порядок в коде. - Стили вне слоёв сильнее стилей в любом
@layer; из двух слоёв сильнее объявленный позже. - Сбросы и базовые стили пишите через
:where()— их перебьёт любой класс без гонки весов. !importantи ID в стилях компонентов — последнее средство: их можно перебить только тем же оружием.
Единицы и функции размера
px
- От чего считается
- CSS-пиксель
- Где удобна
- рамки, тени, мелкие точные размеры
rem
- От чего считается
font-sizeкорня (html); по умолчанию обычно 16px, пользователь может изменить- Где удобна
- шрифты, отступы, брейкпоинты
em
- От чего считается
font-sizeсамого элемента; внутриfont-size— родителя- Где удобна
paddingкнопки, иконка рядом с текстом
%
- От чего считается
- размер содержащего блока;
paddingиmarginв % — от его ширины - Где удобна
- ширина колонок, отступы-пропорции
vw, vh
- От чего считается
- 1% ширины / высоты окна;
vhравенlvh - Где удобна
- полноэкранные блоки на десктопе
dvh, svh, lvh
- От чего считается
- 1% высоты окна: динамической, малой, большой — с учётом панелей мобильного браузера
- Где удобна
- первый экран на телефоне
ch
- От чего считается
- ширина символа «0» в шрифте элемента
- Где удобна
max-widthтекста
fr
- От чего считается
- доля свободного места в Grid
- Где удобна
- колонки сетки
cqi, cqw
- От чего считается
- 1% размера контейнера запроса
- Где удобна
- типографика внутри компонента
html { font-size: 100%; } /* 1rem = размер из настроек браузера, обычно 16px */
.title { font-size: clamp(1.5rem, 1rem + 2.5vw, 3rem); } /* 24px…48px */
.text { max-width: 65ch; } /* около 65 символов в строке */
.btn { font-size: 1.25rem; padding: 0.5em 1em; } /* em — от своего font-size: 10px 20px */
.hero { min-height: 100dvh; } /* высота окна с учётом панелей мобильного браузера */65ch = ширине 65 нулей (520px шрифтом по умолчанию); у кнопки padding: 10px 20px; .hero = высоте окна.clamp(MIN, ЖЕЛАЕМОЕ, MAX) возвращает желаемое значение, пока оно между границами. min(a, b) берёт меньшее, max(a, b) — большее, calc() смешивает единицы: calc(100% - 2rem).
Box model и позиционирование
Блок состоит из содержимого, padding, border и margin. По умолчанию (content-box) width задаёт только содержимое, и отступы с рамкой прибавляются сверху. С border-box width — это внешний размер до рамки включительно.
*, *::before, *::after {
box-sizing: border-box;
}
.box {
width: 300px;
padding: 20px;
border: 2px solid;
/* border-box: снаружи 300px, под контент 300 − 40 − 4 = 256px */
/* content-box: снаружи было бы 300 + 40 + 4 = 344px */
}.box шириной 300px, под содержимое 256px; с content-box тот же блок — 344px.static
- В потоке?
- да
- От чего
top/left - не действуют
- Типичный случай
- значение по умолчанию
relative
- В потоке?
- да, место сохраняется
- От чего
top/left - от своего обычного места
- Типичный случай
- точка отсчёта для
absolute-потомков
absolute
- В потоке?
- нет
- От чего
top/left - от ближайшего предка с
positionнеstatic - Типичный случай
- значок, крестик закрытия
fixed
- В потоке?
- нет
- От чего
top/left - от окна; при
transform/filterу предка — от него - Типичный случай
- плавающая кнопка, оверлей
sticky
- В потоке?
- да
- От чего
top/left - от ближайшего предка с прокруткой; нужен
topили другой отступ - Типичный случай
- шапка таблицы, меню
.card { position: relative; } /* точка отсчёта для absolute-потомков */
.badge { position: absolute; top: 8px; right: 8px; }
.header { position: sticky; top: 0; } /* прилипает к верху при прокрутке */
.overlay {
position: fixed;
inset: 0; /* = top: 0; right: 0; bottom: 0; left: 0 — на всё окно */
}top: 0 после прокрутки на 1500px; .overlay закрывает окно и до, и после прокрутки.Flexbox и Grid: свойства
Flexbox раскладывает элементы по одной оси, Grid — по строкам и колонкам сразу. Подробный разбор с практикой — в уроке о Flexbox и Grid, здесь только «свойство → что делает».
display: flex
- Кому
- контейнер
- Что делает
- делает прямых потомков flex-элементами
flex-direction
- Кому
- контейнер
- Что делает
- главная ось:
row(по умолчанию),column,row-reverse,column-reverse
flex-wrap
- Кому
- контейнер
- Что делает
nowrap(по умолчанию) или перенос на новые строки —wrap
justify-content
- Кому
- контейнер
- Что делает
- распределение по главной оси:
flex-start,center,space-between…
align-items
- Кому
- контейнер
- Что делает
- выравнивание по поперечной оси; по умолчанию
stretch
align-content
- Кому
- контейнер
- Что делает
- распределение строк при
wrap
gap
- Кому
- контейнер
- Что делает
- промежуток между элементами
flex
- Кому
- элемент
- Что делает
flex-growflex-shrinkflex-basis:1=1 1 0%,auto=1 1 auto,none=0 0 auto, безflex—0 1 auto
align-self
- Кому
- элемент
- Что делает
- своё выравнивание по поперечной оси
order
- Кому
- элемент
- Что делает
- меняет только визуальный порядок;
Tabи скринридер идут по HTML
margin-left: auto
- Кому
- элемент
- Что делает
- забирает свободное место и отталкивает элемент вправо
.toolbar {
display: flex;
align-items: center; /* по поперечной оси */
gap: 12px;
flex-wrap: wrap;
}
.toolbar .push { margin-left: auto; } /* прижать этот и следующие элементы вправо */
.columns { display: flex; gap: 16px; }
.columns > * {
flex: 1; /* = 1 1 0%: равные доли */
min-width: 0; /* длинное содержимое не распирает колонку */
}min-width: 0 вторая колонка растягивается больше 3000px.grid-template-columns / -rows
- Кому
- контейнер
- Что делает
- треки:
200px 1fr,repeat(3, 1fr)
repeat(auto-fit, minmax(240px, 1fr))
- Кому
- контейнер
- Что делает
- столько колонок, сколько влезет;
auto-fitрастягивает их,auto-fillоставляет пустые треки
minmax(0, 1fr)
- Кому
- контейнер
- Что делает
- колонка не шире своей доли даже с длинным содержимым
grid-template-areas
- Кому
- контейнер
- Что делает
- макет именованными областями
grid-auto-rows
- Кому
- контейнер
- Что делает
- высота неявно созданных строк
justify-items / align-items / place-items
- Кому
- контейнер
- Что делает
- выравнивание элементов внутри ячеек
grid-area
- Кому
- элемент
- Что делает
- имя области из
grid-template-areas
grid-column: 1 / -1
- Кому
- элемент
- Что делает
- от первой до последней линии — на всю ширину
grid-column: span 2
- Кому
- элемент
- Что делает
- занять две колонки
grid-template-columns: subgrid
- Кому
- вложенная сетка
- Что делает
- взять колонки родительской сетки
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr));
gap: 16px;
}
.page {
display: grid;
grid-template-columns: 240px minmax(0, 1fr);
grid-template-areas:
"head head"
"side main"
"foot foot";
gap: 16px;
}
.page > header { grid-area: head; }
.page > aside { grid-area: side; }
.page > main { grid-area: main; }
.page > footer { grid-area: foot; }
.wide { grid-column: 1 / -1; } /* от первой до последней линии */.page шириной 1000px сайдбар 240px, main 744px даже с длинной строкой, шапка и подвал на всю ширину; .wide на весь ряд.Переменные, медиа- и контейнерные запросы
Пользовательские свойства (custom properties, «CSS-переменные») начинаются с --, читаются через var() и наследуются потомками. Переопределите переменную на компоненте — и изменится всё, что её использует внутри.
:root {
--accent: #2563eb;
--space: 16px;
}
.btn {
background: var(--accent);
padding: var(--space);
color: var(--btn-text, white); /* white, если --btn-text не задана */
}
.btn--danger {
--accent: #dc2626; /* переопределение действует внутри .btn--danger */
}.btn фон #2563eb, у .btn--danger — #dc2626; цвет текста white по запасному значению и black, если --btn-text задана у предка..list { display: grid; gap: 16px; }
@media (width >= 768px) { /* то же, что (min-width: 768px) */
.list { grid-template-columns: 1fr 1fr; }
}
@media (prefers-reduced-motion: reduce) {
.fade { transition: none; }
}
.slot { container-type: inline-size; } /* контейнер для @container */
@container (width > 480px) {
.card { display: grid; grid-template-columns: 160px 1fr; }
}.list при 767px, две при 768px; transition: none при prefers-reduced-motion: reduce; .card — сетка в контейнере 600px и обычный блок в 400px.Что измеряет
@media- окно браузера и настройки устройства
@container- размер ближайшего предка-контейнера
Что нужно объявить
@media- ничего
@containercontainer-type: inline-size(илиsize) у предка
Для чего
@media- раскладка страницы, тема,
prefers-reduced-motion @container- компонент, который стоит то в узкой колонке, то в широкой
Синтаксис диапазона
@media(width >= 768px)=(min-width: 768px)@container(width > 480px)
Современные возможности и их поддержка
Baseline — сводка поддержки в Chrome, Edge, Firefox и Safari (десктоп и мобильные). «Широко доступно» — функция работает во всех этих браузерах не меньше 2,5 лет; «Недавно доступно» — только в последних версиях; «Ограниченно» — ещё не везде. Статусы ниже сняты 12.10.2026 с MDN и пакета web-features 3.42; они меняются — перед использованием проверьте значок Baseline на странице свойства в MDN.
:is(), :where(), :focus-visible
- Что даёт
- короткие списки селекторов, нулевой вес, фокус только с клавиатуры
- Baseline на 12.10.2026
- широко доступно
clamp(), min(), max()
- Что даёт
- размеры без медиазапросов
- Baseline на 12.10.2026
- широко доступно
aspect-ratio, gap у Flexbox
- Что даёт
- пропорции блока, промежутки без
margin - Baseline на 12.10.2026
- широко доступно
dvh, svh, lvh
- Что даёт
- высота окна с учётом панелей браузера
- Baseline на 12.10.2026
- широко доступно
@layer
- Что даёт
- управляемый порядок каскада
- Baseline на 12.10.2026
- широко доступно
Синтаксис (width >= 768px)
- Что даёт
- диапазоны в медиазапросах
- Baseline на 12.10.2026
- широко доступно
@container (размер)
- Что даёт
- адаптивность компонента
- Baseline на 12.10.2026
- широко доступно
color-mix()
- Что даёт
- смешивание цветов в CSS
- Baseline на 12.10.2026
- широко доступно
subgrid
- Что даёт
- вложенная сетка по линиям родителя
- Baseline на 12.10.2026
- широко доступно
:has()
- Что даёт
- выбор родителя и предыдущего элемента
- Baseline на 12.10.2026
- широко доступно
Вложенность &
- Что даёт
- вложенные правила без препроцессора
- Baseline на 12.10.2026
- широко доступно
text-wrap: balance
- Что даёт
- ровные строки заголовков
- Baseline на 12.10.2026
- недавно доступно
@starting-style, light-dark()
- Что даёт
- анимация появления, цвета для светлой и тёмной темы
- Baseline на 12.10.2026
- недавно доступно
@scope, field-sizing
- Что даёт
- область действия стилей, поле по размеру текста
- Baseline на 12.10.2026
- недавно доступно
Контейнерные запросы по стилю
- Что даёт
@container style(--x: y)- Baseline на 12.10.2026
- недавно доступно
Анимации по прокрутке (animation-timeline)
- Что даёт
- анимация, привязанная к прокрутке
- Baseline на 12.10.2026
- ограниченно
/* Вложенность без препроцессора */
.card {
padding: 16px;
& .title { font-size: 1.25rem; }
&:hover { outline: 2px solid; }
}
/* Слои каскада: более поздний слой сильнее, специфичность не важна */
@layer reset, components;
@layer reset { #app button { margin: 0; } } /* 1-0-1 */
@layer components { .btn { margin: 8px; } } /* 0-1-0 — побеждает */
/* Ветка только для браузеров с поддержкой :has() */
@supports selector(:has(a)) {
.card:has(img) { display: grid; grid-template-columns: 120px 1fr; }
}.title — 20px через вложенность, у кнопки margin: 8px из более позднего слоя, хотя правило #app button тяжелее; ветка @supports применилась.Центрирование и частые ловушки
/* 1. Grid: по обеим осям одной строкой */
.center-grid {
display: grid;
place-items: center;
}
/* 2. Flex: то же, плюс удобно для нескольких элементов в ряд */
.center-flex {
display: flex;
justify-content: center;
align-items: center;
}
/* 3. Контейнер страницы по горизонтали */
.container {
max-width: 1200px;
margin-inline: auto;
}
/* 4. Поверх родителя (модалка, значок) */
.center-abs-parent { position: relative; }
.center-abs {
position: absolute;
top: 50%;
left: 50%;
translate: -50% -50%;
}.container шириной 1200px стоит с отступом 40px в окне 1280px.один блок по обеим осям
- Рецепт
display: grid; place-items: center
несколько элементов в ряд
- Рецепт
display: flex; justify-content: center; align-items: center
контейнер страницы
- Рецепт
max-width+margin-inline: auto
строчный текст и кнопки внутри блока
- Рецепт
text-align: center
поверх содержимого
- Рецепт
position: absolute; top: 50%; left: 50%; translate: -50% -50%
top и z-index не действуют
- Причина
- у элемента
position: static - Исправление
position: relative
sticky не прилипает
- Причина
- нет
topили у предкаoverflow: hidden - Исправление
- задать
top, убратьoverflowу предка
z-index: 9999 под соседом
- Причина
- элемент в другом контексте наложения (у родителя свой
z-index) - Исправление
- поднимать родителя, а не ребёнка
fixed отсчитывается не от окна
- Причина
- у предка
transform,filterилиtranslate - Исправление
- вынести элемент из такого предка
width: 100% + padding вылезает
- Причина
content-box- Исправление
box-sizing: border-box
колонку распирает длинное слово или код
- Причина
- минимальная ширина flex- и grid-элемента — по содержимому
- Исправление
min-width: 0илиminmax(0, 1fr)
100vh на телефоне выше экрана
- Причина
vhсчитается от большой высоты окна- Исправление
100dvhили100svh
@container не срабатывает
- Причина
- у предка нет
container-type - Исправление
container-type: inline-size
Готовые утилиты для всего этого есть в Tailwind CSS: grid place-items-center, mx-auto, min-w-0, @container, — разбор в уроке о Tailwind CSS.
Как проверено4 · пройденосверено 12 октября 2026 г.
- запущено, работает
has.css, specificity.css, units.css, box.css, position.css, flex.css, grid.css, vars.css, queries.css, center.css (RU и EN-версии комментариев)
check.mjs: Microsoft Edge 155.0.4283.45 через Playwright 1.64 (channel msedge), getComputedStyle и getBoundingClientRect — 52 проверки для каждого из двух наборов файлов, 0 ошибок консоли. Ключевые значения: :is(.menu,#top) a побеждает (синий); clamp 24/36/48px при 320/800/1600px; 65ch = 520px; padding 10px 20px; 100dvh = 700px; border-box 300/256, content-box 344; значок 8/8px; sticky y=0 после прокрутки; колонки flex по 200px с min-width:0 и >3000px без него; flex: 1 → 1 1 0%; auto-fit 1/3/4 колонки при 375/800/1280; области 240/744; var() в @media не работает; @media 767→1, 768→2; reduced-motion 0s; @container 400→block, 600→grid, без container-type — block; три способа центрирования со смещением 0px
- запущено, работает
modern.css (вложенность, @layer, @supports)
modern-check.mjs, Edge 155: .title 20px, margin 8px из более позднего слоя против #app button, @supports-ветка применилась, :hover даёт outline 2px; RU и EN
- запущено, работает
таблицы селекторов и специфичности
sel-table.mjs: 12 селекторов из таблицы через querySelectorAll + ::after content; spec-table.mjs: 10 пар правил (более слабое ниже по коду) + inline против #id и !important против inline — все победители совпали с таблицей
- запущено, работает
утверждения таблиц (единицы, flex/grid, ловушки)
props.mjs, Edge 155: em/rem/%/vw; flex auto/none/по умолчанию; stretch, space-between; order не меняет порядок Tab; span 2, grid-auto-rows, auto-fill vs auto-fit 100/500px; CSS.supports для subgrid, :has, container-type, dvh, color-mix, text-wrap: balance; @layer и стили вне слоёв; top у static; sticky в overflow:hidden; z-index 9999 под соседом; fixed внутри transform; width:100%+padding = 340px — 34 проверки
«Запущено» — код выполнен во временном проекте или контейнере, вывод в статье взят из прогона. «Частично» — проверено с заглушками вместо внешних сервисов. «Не запускалось» — нужны устройство, аккаунт или ключ; шаги сверены с официальной документацией. Файлы проверочного проекта и логи запусков сохранены в архиве InterLAB.