Типизированные переменные: @property
Обычная CSS-переменная из урока «CSS-переменные» — просто кусок текста. Браузер не знает, что в --accent лежит цвет, а в --angle — угол, и поэтому не умеет плавно менять их значение. Правило @property регистрирует переменную: сообщает её тип, наследуется ли она и чему равна по умолчанию.
Переменная без типа
Градиент нельзя анимировать напрямую, но можно менять цвет внутри него через переменную. Наведите курсор на кнопку:
<style>
.btn {
--from: tomato;
padding: 12px 24px;
border: 0;
color: white;
background: linear-gradient(90deg, var(--from), gold);
transition: --from 0.6s;
}
.btn:hover { --from: rebeccapurple; }
</style>
<button class="btn">Наведите</button>Цвет сменился рывком, хотя переход указан: для браузера tomato и rebeccapurple — просто два слова, промежуточных значений между ними нет.
Правило @property
Зарегистрируем --from как цвет — и тот же переход станет плавным:
<style>
@property --from {
syntax: "<color>";
inherits: false;
initial-value: tomato;
}
.btn {
padding: 12px 24px;
border: 0;
color: white;
background: linear-gradient(90deg, var(--from), gold);
transition: --from 0.6s;
}
.btn:hover { --from: rebeccapurple; }
</style>
<button class="btn">Наведите</button>Теперь браузер знает, что это цвет, и считает все оттенки между двумя значениями.
Три описания
| Описание | Что задаёт |
|---|---|
syntax | тип значения в кавычках |
inherits | true — дети получают значение от родителя, false — нет |
initial-value | значение, если переменную нигде не задали |
Типы пишут в угловых скобках:
| Тип | Пример значения |
|---|---|
<color> | tomato, #ff6347 |
<length> | 12px, 2rem |
<percentage> | 50% |
<number> | 1.5 |
<angle> | 45deg, 0.5turn |
* | что угодно, как у обычной переменной |
Вращение угла
Угол тоже можно анимировать. Конический градиент conic-gradient() раскрашивает блок секторами вокруг центра, как циферблат, а слово from задаёт угол, с которого он начинается. Подставим туда переменную --angle:
<style>
@property --angle {
syntax: "<angle>";
inherits: false;
initial-value: 0deg;
}
@keyframes spin {
to { --angle: 360deg; }
}
.ring {
width: 120px;
height: 120px;
border-radius: 50%;
background: conic-gradient(from var(--angle), tomato, gold, seagreen, tomato);
animation: spin 3s linear infinite;
}
</style>
<div class="ring"></div>Вращается не сам блок, а только градиент внутри него. Так же делают переливающиеся рамки кнопок.
Проверка типа
Зарегистрированная переменная не принимает значение чужого типа: такое объявление браузер пропускает и берёт initial-value:
<style>
@property --gap {
syntax: "<length>";
inherits: false;
initial-value: 8px;
}
.box { margin: 4px 0; padding: var(--gap); background: lavender; }
.big { --gap: 30px; }
.wrong { --gap: red; }
</style>
<div class="box big">--gap: 30px</div>
<div class="box wrong">--gap: red — не длина, взято 8px</div>@property поддерживается во всех основных браузерах с 2024 года.
Частая ошибка
Пропустить initial-value или inherits. Без них правило @property недействительно целиком, переменная остаётся обычной — и анимация снова идёт рывком:
<style>
@property --from {
syntax: "<color>";
inherits: false;
}
.btn {
--from: tomato;
padding: 12px 24px;
border: 0;
color: white;
background: linear-gradient(90deg, var(--from), gold);
transition: --from 0.6s;
}
.btn:hover { --from: rebeccapurple; }
</style>
<button class="btn">Рывок: нет initial-value</button>Только тип * можно оставить без начального значения. Для всех остальных типов пишите все три описания.