Начнём сразу с результата — флаг из двух полос, нарисованный одним правилом:
.flag--ukraine {
aspect-ratio: 3 / 2;
background: linear-gradient(#0057b7 50%, #ffd700 50%);
}
Никаких картинок и вложенных блоков: синяя половина и жёлтая половина — это один градиент. Разберёмся, почему он не плавный, а с чёткой границей.
Градиент — это картинка
Первое, что стоит запомнить: linear-gradient() возвращает не цвет, а изображение. Браузер рисует его на лету, но для CSS это то же самое, что url(photo.jpg).
Отсюда частая ошибка новичков:
/* не сработает: background-color принимает только цвет */
.card {
background-color: linear-gradient(#0057b7, #ffd700);
}
/* сработает: градиент — это фоновое изображение */
.card {
background-image: linear-gradient(#0057b7, #ffd700);
}
/* или шорткат background, как во всех примерах мануала */
.card {
background: linear-gradient(#0057b7, #ffd700);
}
Второе следствие: у градиента нет собственного размера. Он растягивается на весь блок, а если блок пустой и без размеров, то и рисовать не на чем.
Заготовка для флагов
Все флаги в мануале строятся на одном базовом классе. Флаг ведёт себя почти как картинка: стоит в строке текста и растёт вместе со шрифтом.
.flag {
display: inline-grid; /* стоит в строке, как <img> */
height: 1em; /* высота = размер шрифта */
vertical-align: top; /* ровнее встаёт рядом с текстом */
position: relative; /* опора для ::before/::after в главе 7 */
overflow: hidden; /* всё, что вылезло, обрезаем */
}
Ширину не задаём: у каждой страны свои пропорции, и их проще всего выразить через aspect-ratio. При фиксированной высоте ширина посчитается сама. Если забыть aspect-ratio, у пустого элемента не будет ширины, и флаг просто исчезнет. Подробнее о пропорциях — в статье про aspect-ratio.
Внутри строки текста используем <span>, а не <div>: блочный элемент внутри абзаца — невалидная разметка.
<p>Финал разыграют
<span class="flag flag--ukraine"></span> Украина и
<span class="flag flag--lithuania"></span> Литва.
</p>
В отдельных демо высота флагов задана в пикселях, чтобы их было лучше видно, но код самих флагов от этого не меняется.
Цветовые стопы
Внутри скобок градиента перечисляются цветовые стопы — цвет и (необязательно) его позиция. По умолчанию линейный градиент идёт сверху вниз, так что позиции отсчитываются от верхнего края.
- Позиций нет совсем — цвета распределяются равномерно, а переход занимает всю высоту.
- Позиции есть — цвет «чистый» до своей позиции, а между двумя стопами идёт плавное смешивание.
- Две позиции совпали — на смешивание не осталось места, получается жёсткая граница.
/* переход на всю высоту */
.box--smooth { background: linear-gradient(#0057b7, #ffd700); }
/* до 40% синий, с 60% жёлтый, между ними — переход */
.box--zone { background: linear-gradient(#0057b7 40%, #ffd700 60%); }
/* стопы в одной точке — переход нулевой ширины */
.box--hard { background: linear-gradient(#0057b7 50%, #ffd700 50%); }
Флаги почти целиком состоят из жёстких границ, поэтому дальше нас интересует в основном третий вариант.
Полосы: два значения у одного цвета
У цвета может быть сразу две позиции — где он начинается и где заканчивается. Так удобно описывать полосы:
.flag--lithuania {
aspect-ratio: 5 / 3;
background: linear-gradient(
#fdb913 0% 33.33%,
#006a44 33.33% 66.67%,
#c1272d 66.67% 100%
);
}
Запись длинная, но читается как таблица: жёлтый от 0 до трети, зелёный от трети до двух третей, красный до конца.
Теперь сократим её по двум правилам:
- Первый цвет и так начинается с 0, а последний и так заканчивается на 100%, поэтому эти позиции можно не писать.
- Если позиция стопа меньше предыдущей, браузер подтягивает её до предыдущей. Значит, вместо точного начала полосы можно поставить 0 — граница всё равно окажется там, где кончился прошлый цвет.
.flag--lithuania {
aspect-ratio: 5 / 3;
background: linear-gradient(#fdb913 33.33%, #006a44 0 66.67%, #c1272d 0);
}
Этот приём с 0 встретится во всех следующих главах. Читать его стоит так: «новый цвет начинается сразу там, где кончился предыдущий».
Подсказка перехода
Между двумя цветами можно поставить одинокое значение без цвета — подсказку перехода (transition hint). Она говорит, в какой точке смесь должна быть ровно пополам:
/* середина смеси — на 50%, как обычно */
.box--plain { background: linear-gradient(#7048e8, #ffd43b); }
/* середина смеси сдвинута к 20%: жёлтый «захватывает» больше места */
.box--hint { background: linear-gradient(#7048e8, 20%, #ffd43b); }
Для флагов это не нужно, а вот для мягких фонов и теней из градиентов — удобно: переход становится несимметричным без лишних стопов.
Ещё одна настройка плавных градиентов — цветовое пространство, в котором браузер смешивает цвета (linear-gradient(in oklch, …)). Она убирает серую «грязь» посередине между яркими цветами; подробный разбор с примерами — в статье про OKLCH.
Что запомнить
- Градиент — это изображение: его кладут в background или background-image, но не в background-color.
- Стопы в одной точке дают жёсткую границу.
- 0 в начале полосы означает «сразу после предыдущего цвета».
- Пустому элементу нужны размеры — у нас это высота плюс aspect-ratio.