Сокращённые свойства CSS экономят строки, но взамен требуют помнить порядок значений. Четыре числа в margin ничем не подписаны: перепутал второе с четвёртым — и отступ уехал не в ту сторону. То же самое с псевдоклассами ссылки: правила написаны верно, но в неудачном порядке, и наведение мышью перестаёт работать на половине ссылок.

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

TRouBLe: порядок сторон в сокращённых свойствах

Самая известная подсказка касается отступов. Английское слово TRouBLe складывается из первых букв четырёх сторон: Top, Right, Bottom, Left — верх, право, низ, лево. Именно в этом порядке значения идут в margin и padding.

Если слово не запоминается, есть геометрический вариант: стороны перечисляются по часовой стрелке, начиная с двенадцати часов. Верх → право → низ → лево.

.promo-card {
  margin-top: 24px;
  margin-right: 16px;
  margin-bottom: 32px;
  margin-left: 16px;
}

/* то же самое одной строкой */
.promo-card {
  margin: 24px 16px 32px 16px;
}

Одно, два и три значения: что чему достаётся

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

Запись Как читается
padding: 20px все четыре стороны по 20px
padding: 20px 12px верх и низ по 20px, право и лево по 12px
padding: 20px 12px 8px верх 20px, право и лево по 12px, низ 8px
padding: 20px 12px 8px 4px верх 20px, право 12px, низ 8px, лево 4px

Форма с тремя значениями ломает больше всего верстальщиков. Кажется, что после верха и права логично идёт низ — на самом деле третье значение и есть низ, а вот лево просто копирует право. Запись padding: 16px 0 0 означает «отступ сверху, всё остальное по нулям», а не «сверху и слева».

/* симметричная кнопка: вертикаль одна, горизонталь другая */
.btn {
  padding: 10px 22px;
}

/* хлебные крошки: нужен отступ только сверху */
.breadcrumbs {
  margin: 16px 0 0;   /* право, лево и низ обнулены */
}

Где TRouBLe работает, кроме отступов

Подсказка шире, чем кажется: тот же порядок сторон действует у всех сокращений, которые описывают рамку, и у свойства позиционирования inset.

  • border-width, border-style, border-color;
  • inset — сокращение для top, right, bottom, left сразу;
  • scroll-margin и scroll-padding — отступы для прокрутки к якорю.
/* бейдж в правом верхнем углу карточки */
.card { position: relative; }

.card__badge {
  position: absolute;
  inset: 8px 8px auto auto;   /* верх 8px, право 8px, низ и лево не задаём */
}

/* рамка только снизу, без четырёх отдельных свойств */
.tab--active {
  border-style: none none solid;
  border-width: 0 0 2px;
  border-color: transparent transparent #2f80ed;
}

Со scroll-margin история жизненная: если на странице фиксированная шапка, то переход по якорю прячет заголовок под ней. Отступ сверху решает вопрос одной строкой — подробнее эта задача разобрана в статье про якорные ссылки с фиксированным хедером.

Где мнемоника врёт

Привычка «четыре значения = верх, право, низ, лево» настолько въедается, что её начинают применять ко всему подряд. А есть свойства, которые считают по-другому.

border-radius идёт по углам, а не по сторонам

У скруглений тоже четыре значения и тоже по часовой стрелке, но точка старта другая: не верхняя сторона, а левый верхний угол. Порядок такой: верхний левый → верхний правый → нижний правый → нижний левый.

.bubble {
  border-radius: 16px 16px 16px 2px;
  /* скруглено всё, кроме нижнего левого угла — получился хвостик реплики */
}

/* два значения задают диагонали */
.leaf {
  border-radius: 24px 4px;   /* ↖ и ↘ по 24px, ↗ и ↙ по 4px */
}

Логические свойства считают от начала строки

Логические свойства описывают не «верх и низ», а «начало и конец» относительно направления текста. Поэтому у них по два значения, и читаются они как start / end, а не как противоположные стороны.

.note {
  margin-inline: 12px 32px;   /* начало строки 12px, конец строки 32px */
  margin-block: 24px 8px;     /* над блоком 24px, под блоком 8px */
}

В привычной горизонтальной раскладке слева направо margin-inline: 12px 32px даст 12px слева и 32px справа. В раскладке справа налево стороны поменяются местами автоматически — ровно ради этого логические свойства и заводили. Как направление письма влияет на вёрстку целиком, разобрано в материале про CSS writing modes.

Ловушка в том, что inset при этом остался физическим и живёт по TRouBLe, а его логический двойник называется inset-inline и снова считает start / end. Два похожих имени — две разные системы координат.

Поддержка браузерами
chrome
Chrome
89
firefox
Firefox
66
edge
Edge
89
safari
Safari
15
opera
Opera
76

grid-area считает по линиям сетки

Ещё одно свойство с четырьмя значениями, которое не имеет к сторонам никакого отношения: grid-area перечисляет линии грида в порядке начало строки → начало колонки → конец строки → конец колонки.

.hero {
  grid-area: 1 / 1 / 3 / 4;   /* строки с 1 по 3, колонки с 1 по 4 */
}

LoVe HAte: порядок псевдоклассов ссылки

Вторая классическая мнемоника — про ссылки. Четыре состояния должны идти строго в порядке :link, :visited, :hover, :active. Первые буквы складываются в LVHA, а чтобы это выговаривалось, порядок читают как английское «LoVe HAte».

Причина не в красоте, а в каскаде. Все четыре псевдокласса весят одинаково: специфичность у каждого одна и та же, поэтому при конфликте побеждает то правило, которое написано ниже. Если :visited окажется после :hover, он перебьёт наведение — и посещённые ссылки перестанут реагировать на курсор.

/* так делать не надо: :visited ниже и забирает себе посещённые ссылки */
a:hover   { color: #c0392b; }
a:visited { color: #6b4fa0; }
/* правильный порядок: LoVe HAte */
a:link    { color: #2f80ed; }
a:visited { color: #6b4fa0; }
a:hover   { color: #c0392b; }
a:active  { color: #8e2b20; }

Куда в этой цепочке ставить фокус

Правило LoVe HAte придумано до того, как в вёрстке появилась привычка отдельно оформлять клавиатурный фокус. Сегодня псевдоклассов пять, и :focus-visible вставляют между :visited и :hover — тогда наведение мышью поверх сфокусированной ссылки всё равно меняет цвет.

a:link          { color: #2f80ed; }
a:visited       { color: #6b4fa0; }
a:focus-visible { outline: 2px solid #2f80ed; outline-offset: 3px; }
a:hover         { color: #c0392b; }
a:active        { color: #8e2b20; }

Конфликта обычно и не возникает: фокус чаще всего рисуют через outline, а наведение меняет color или background — разные свойства друг друга не перекрывают. Но если фокус и ховер спорят за одно и то же свойство, приоритет стоит отдать фокусу и опустить его ниже :hover: пропавшая под курсором рамка фокуса — это потерянная клавиатурная навигация, а не косметика. Подробности про такие ситуации — в подборке советов по вёрстке под клавиатурную навигацию.

Ещё один нюанс, о котором легко забыть: :link срабатывает только на элементах <a> с атрибутом href. Ссылка-заглушка без адреса не получит ни одно из четырёх состояний, сколько правил под неё ни пиши.

Поддержка браузерами
chrome
Chrome
86
firefox
Firefox
85
edge
Edge
86
safari
Safari
15.4
opera
Opera
72

Круг оттенков: шесть цветов через каждые 60°

Третья подсказка живёт в мире цвета. Первый параметр функции hsl() — это угол на цветовом круге, и шесть опорных точек стоят ровно через 60°. Порядок оттенков от 60° и дальше складывается в цепочку Y — G — C — B — M — R: жёлтый, зелёный, голубой, синий, пурпурный, красный. Для запоминания используют фразу Young Guys Can Be Messy Radicals (что в переводе означает "Молодые парни могут быть неорганизованными радикалами").

Угол Оттенок Буква в цепочке
0° и 360° красный R — Red
60° жёлтый Y — Yellow
120° зелёный G — Green
180° голубой C — Cyan
240° синий B — Blue
300° пурпурный M — Magenta

Зачем это помнить: имея опорные точки, палитру можно собирать в уме. Противоположный цвет — это плюс 180°, триада — шаг в 120° в обе стороны, аналогичные оттенки — плюс-минус 30°. Никакого цветового круга под рукой при этом не нужно.

:root {
  --brand:  hsl(210 90% 45%);   /* синий, между 180° и 240° */
  --accent: hsl(30 90% 45%);    /* 210 + 180 = 30° — оранжевый, контраст к бренду */
}

Больше приёмов с этой функцией — в отдельном разборе использования HSL-цвета в CSS.

Поворот оттенка без пересчёта в уме

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

:root {
  --brand: hsl(210 90% 45%);
}

.accent {
  /* тот же цвет, повёрнутый на полкруга: насыщенность и яркость не трогаем */
  background: hsl(from var(--brand) calc(h + 180) s l);
}

.accent--soft {
  /* соседний оттенок для мягкого градиента */
  background: hsl(from var(--brand) calc(h + 30) s l);
}

Мнемоника при этом не устаревает, а наоборот становится полезнее: чтобы осмысленно прибавить градусы, надо представлять, куда именно на круге переедет цвет.

Поддержка браузерами
chrome
Chrome
131
firefox
Firefox
133
edge
Edge
131
safari
Safari
18
opera
Opera
117

Важная оговорка про oklch

Цепочка Y–G–C–B–M–R описывает круг именно функции hsl(). В современной oklch() угол тоже называется hue, но система координат другая, и одно и то же число даёт другой цвет: hsl(120 90% 45%) и oklch(0.6 0.2 120) — не один зелёный, а два разных оттенка. Переносить заученные углы из одной функции в другую нельзя, для oklch() опорные точки придётся запоминать заново. Чем эта функция вообще хороша и зачем на неё переходят — в статье про oklch в CSS.

Ещё несколько порядков, которые стоит держать в голове

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

flex: расти, сжимайся, с чего начать

Три значения идут в порядке flex-grow, flex-shrink, flex-basis: насколько элемент готов расти, насколько готов сжиматься и от какого размера отсчитывать.

.sidebar { flex: 0 0 280px; }   /* не растёт, не сжимается, ширина ровно 280px */
.content { flex: 1; }           /* сокращение от flex: 1 1 0% */

Форма с одним числом сбивает с толку чаще всего: flex: 1 — это не только «расти», но и базовый размер 0%. Поэтому два элемента с flex: 1 получат одинаковую ширину независимо от того, сколько текста внутри.

box-shadow: сместить, размыть, раздуть

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

.card {
  box-shadow: 0 8px 24px -6px rgba(15, 23, 42, 0.35);
  /*          x  y  размытие  растяжение  цвет */
}

Отрицательное растяжение поджимает тень со всех сторон — так и делается мягкая тень под карточкой, которая не вылезает из-под неё по бокам.

transition: первое время — длительность, второе — задержка

В сокращении transition порядок значений почти свободный, кроме одного жёсткого правила: из двух временных значений первое всегда длительность, второе — задержка перед стартом.

.tooltip {
  transition: opacity 200ms ease-out 400ms;
  /*          что     сколько  как      после какой паузы */
}

Если поменять числа местами, всплывашка будет появляться 400 мс после паузы в 200 мс — вроде мелочь, а ощущается как тормозящий интерфейс. Остальные тонкости этого свойства собраны в обзоре CSS-переходов.

background-position: сначала по горизонтали

Два значения задают позицию фона, и здесь порядок обратный привычке начинать сверху: сперва идёт горизонталь, потом вертикаль.

.hero {
  background-position: 20px 60px;   /* 20px слева, 60px сверху */
}

.hero--named {
  background-position: right top;   /* то же самое словами */
}

Со словесными значениями порядок роли не играет — браузер понимает, что top right и right top это одно и то же. А вот числа читаются строго как X и Y.

Шпаргалка

Что Порядок Подсказка
margin, padding, border-width, inset верх, право, низ, лево TRouBLe, по часовой с 12 часов
border-radius верхний левый, верхний правый, нижний правый, нижний левый по часовой, но с угла
margin-inline, margin-block начало, конец start и end, а не стороны
grid-area начало строки, начало колонки, конец строки, конец колонки сначала оба начала, потом оба конца
псевдоклассы ссылки :link, :visited, :hover, :active LoVe HAte
угол в hsl() 60° жёлтый, 120° зелёный, 180° голубой, 240° синий, 300° пурпурный, 0° красный Y-G-C-B-M-R через 60°
flex рост, сжатие, базовый размер расти, сжимайся, с чего начать
box-shadow X, Y, размытие, растяжение, цвет сместить, размыть, раздуть
transition первое время — длительность, второе — задержка сначала сколько, потом когда
background-position горизонталь, вертикаль X, потом Y

Мнемоника не заменяет понимание, но экономит те самые тридцать секунд, за которые мысль о вёрстке успевает выветриться. Кстати, тот же приём работает и с названиями тегов: многие из них — сокращения английских слов, и стоит их один раз расшифровать, как запоминание перестаёт быть зубрёжкой. Готовая таблица есть в материале про расшифровку HTML-тегов.