Сокращённые свойства 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. Два похожих имени — две разные системы координат.
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. Ссылка-заглушка без адреса не получит ни одно из четырёх состояний, сколько правил под неё ни пиши.
Круг оттенков: шесть цветов через каждые 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);
}
Мнемоника при этом не устаревает, а наоборот становится полезнее: чтобы осмысленно прибавить градусы, надо представлять, куда именно на круге переедет цвет.
Важная оговорка про 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-тегов.
Комментарии (0)