`@starting-style` CSS at-rule
Базовая поддержка Новая возможность
Эта возможность поддерживается в последних версиях устройств и браузеров. Она может не работать на старых устройствах и в старых версиях браузеров. Поддержка во всех браузерах появилась в августе 2024 года.
Правило @starting-style CSS at-rule используется для задания начальных значений свойств элемента, от которых должен выполняться переход при первом обновлении его стилей, то есть когда элемент впервые отображается на уже загруженной странице.
Синтаксис
Правило @starting-style можно использовать двумя способами:
-
Как самостоятельный блок, содержащий один или несколько наборов правил, которые задают начальные стили и выбирают элементы, к которым они применяются:
@starting-style { /* rulesets */ } -
Вложить в существующий набор правил. В этом случае оно содержит одно или несколько объявлений, задающих начальные значения свойств для элементов, уже выбранных этим набором правил:
selector { /* existing ruleset */ /* ... */ @starting-style { /* declarations */ } }
Описание
Чтобы избежать неожиданного поведения, CSS-переходы по умолчанию не запускаются при первоначальном обновлении стилей элемента или при изменении типа display с none на другое значение. Для включения переходов при первом обновлении стилей нужны правила @starting-style. Они задают начальные стили для элементов, у которых нет предыдущего состояния, и определяют значения свойств, с которых начинается переход.
@starting-style особенно полезно при создании переходов появления и исчезновения для элементов, отображаемых в верхнем слое (например, всплывающих окон и модальных <dialog>), элементов, которые переключаются в display: none и обратно, а также элементов, которые впервые добавляются в DOM или удаляются из него.
Примечание: @starting-style имеет значение только для CSS-переходов. При использовании CSS-анимаций для создания таких эффектов @starting-style не требуется. Пример см. в разделе Использование CSS-анимаций.
Использовать @starting-style можно двумя способами: как самостоятельное правило или внутри набора правил.
Рассмотрим ситуацию, когда нужно анимировать всплывающее окно при его отображении (то есть при добавлении в верхний слой). «Исходное правило», задающее стили открытого всплывающего окна, может выглядеть примерно так (см. пример анимации всплывающего окна ниже):
[popover]:popover-open {
opacity: 1;
transform: scaleX(1);
}
Чтобы задать начальные значения свойств всплывающего окна, которые будут анимироваться первым способом, добавьте в CSS самостоятельный блок @starting-style:
@starting-style {
[popover]:popover-open {
opacity: 0;
transform: scaleX(0);
}
}
Примечание: Правило @starting-style и «исходное правило» имеют одинаковую специфичность. Чтобы начальные стили применялись, добавьте правило @starting-style после «исходного правила». Если указать правило @starting-style перед «исходным правилом», исходные стили переопределят начальные.
Чтобы задать начальный стиль всплывающего окна вложенным способом, можно поместить блок @starting-style внутрь «исходного правила»:
[popover]:popover-open {
opacity: 1;
transform: scaleX(1);
@starting-style {
opacity: 0;
transform: scaleX(0);
}
}
Когда именно используются начальные стили?
Важно понимать, что при первой отрисовке элемента в DOM или при переходе от @starting-style к видимому значению выполняется переход от его стилей display: none. При переходе обратно из первоначального видимого состояния стили @starting-style больше не используются, поскольку элемент уже виден в DOM. Вместо этого выполняется переход к стилям, заданным для состояния элемента по умолчанию.
В таких ситуациях фактически нужно управлять тремя состояниями стилей: начальным, состоянием после перехода и состоянием по умолчанию. В подобных случаях переходы «к» и «от» могут различаться. Это можно увидеть в приведённом ниже примере «Демонстрация использования начальных стилей».
Формальный синтаксис
@starting-style = @starting-style { <rule-list> } Примеры
Базовое использование @starting-style
При первой отрисовке элемента выполните переход его background-color от прозрачного к зелёному:
#target {
transition: background-color 1.5s;
background-color: green;
}
@starting-style {
#target {
background-color: transparent;
}
}
Выполните переход opacity элемента при изменении его значения display на none или обратно:
#target {
transition-property: opacity, display;
transition-duration: 0.5s;
display: block;
opacity: 1;
@starting-style {
opacity: 0;
}
}
#target.hidden {
display: none;
opacity: 0;
}
Демонстрация использования начальных стилей
В этом примере нажмите кнопку, чтобы создать элемент <div>, задать ему class со значением showing и добавить его в DOM.
Для showing задаётся @starting-style со значением background-color: red и стиль background-color: blue, к которому выполняется переход. Набор правил div по умолчанию содержит background-color: yellow; здесь же задаётся transition.
Когда <div> впервые добавляется в DOM, цвет фона меняется с красного на синий. По истечении времени мы удаляем класс showing из <div> с помощью JavaScript. В этот момент цвет меняется с синего обратно на жёлтый, а не на красный. Это доказывает, что начальные стили используются только при первой отрисовке элемента в DOM. После появления элемента выполняется переход обратно к заданному для него стилю по умолчанию.
По истечении ещё одного промежутка времени мы полностью удаляем <div> из DOM, сбрасывая исходное состояние примера, чтобы его можно было запустить снова.
HTML
<button>Display <code><div></code></button>
CSS
div {
width: 200px;
height: 100px;
border: 1px solid black;
margin-top: 10px;
}
div::after {
content: "class: " attr(class);
position: relative;
top: 3px;
left: 3px;
}
div {
background-color: yellow;
transition: background-color 3s;
}
div.showing {
background-color: skyblue;
}
@starting-style {
div.showing {
background-color: red;
}
}
JavaScript
const btn = document.querySelector("button");
btn.addEventListener("click", () => {
btn.disabled = true;
const divElem = document.createElement("div");
divElem.classList.add("showing");
document.body.append(divElem);
setTimeout(() => {
divElem.classList.remove("showing");
setTimeout(() => {
divElem.remove();
btn.disabled = false;
}, 3000);
}, 3000);
});
Результат
Код отображается следующим образом:
Анимация всплывающего окна
В этом примере для анимации всплывающего окна используются CSS-переходы. Базовые анимации появления и исчезновения задаются с помощью свойства transition.
HTML
В HTML содержится элемент <div>, объявленный всплывающим окном с помощью атрибута popover, и элемент <button>, назначенный элементом управления отображением всплывающего окна с помощью атрибута popovertarget.
<button popovertarget="mypopover">Show the popover</button> <div popover="auto" id="mypopover">I'm a Popover! I should animate.</div>
CSS
В этом примере нужно анимировать два свойства: opacity и transform (в частности, трансформацию с горизонтальным масштабированием), чтобы всплывающее окно плавно появлялось и исчезало, а также увеличивалось и уменьшалось по горизонтали.
html {
font-family: "Helvetica", "Arial", sans-serif;
}
[popover]:popover-open {
opacity: 1;
transform: scaleX(1);
}
[popover] {
font-size: 1.2rem;
padding: 10px;
/* Final state of the exit animation */
opacity: 0;
transform: scaleX(0);
transition:
opacity 0.7s,
transform 0.7s,
overlay 0.7s allow-discrete,
display 0.7s allow-discrete;
/* Equivalent to
transition: all 0.7s allow-discrete; */
}
/* Include after the [popover]:popover-open rule */
@starting-style {
[popover]:popover-open {
opacity: 0;
transform: scaleX(0);
}
}
/* Transition for the popover's backdrop */
[popover]::backdrop {
background-color: transparent;
transition:
display 0.7s allow-discrete,
overlay 0.7s allow-discrete,
background-color 0.7s;
/* Equivalent to
transition: all 0.7s allow-discrete; */
}
[popover]:popover-open::backdrop {
background-color: rgb(0 0 0 / 25%);
}
/* Nesting (&) is not supported for pseudo-elements
so specify a standalone starting-style block. */
@starting-style {
[popover]:popover-open::backdrop {
background-color: transparent;
}
}
Для этого мы задали начальное состояние этих свойств для скрытого по умолчанию состояния элемента всплывающего окна (выбранного с помощью [popover]), а конечное состояние — для открытого состояния всплывающего окна (выбранного с помощью псевдокласса :popover-open).
Затем мы задали свойство transition, чтобы анимировать переход между этими двумя состояниями. Начальное состояние анимации находится внутри правила @starting-style, которое включает анимацию появления.
Так как при отображении анимируемый элемент перемещается в верхний слой, а при скрытии удаляется из него (с помощью display: none), для корректной работы анимации в обоих направлениях нужны дополнительные действия:
-
displayдобавляется в список анимируемых элементов, чтобы анимируемый элемент оставался видимым (значениеdisplay: blockили другое видимое значениеdisplay) на протяжении всей анимации появления и исчезновения. Без этого анимация исчезновения не будет видна: всплывающее окно просто исчезнет. Обратите внимание, что значениеtransition-behavior: allow-discreteтакже задаётся в сокращённой записи, чтобы активировать анимацию. -
overlayдобавляется в список анимируемых элементов, чтобы удаление элемента из верхнего слоя откладывалось до окончания анимации. Для подобных анимаций это не так важно, но в более сложных случаях без этого элемент может быть слишком быстро удалён из наложения, и анимация станет прерывистой или неэффективной. И здесь для выполнения анимации требуетсяtransition-behavior: allow-discrete.
Примечание: Мы также добавили переход для ::backdrop, появляющегося за всплывающим окном при его открытии, чтобы создать приятный эффект затемнения. Для выбора фона при открытом всплывающем окне используется [popover]:popover-open::backdrop.
Результат
Код отображается следующим образом:
Примечание: Поскольку при каждом отображении всплывающие окна меняют состояние с display: none на display: block, во время каждого перехода появления они переходят от стилей @starting-style к стилям [popover]:popover-open. При закрытии всплывающее окно переходит из состояния [popover]:popover-open в состояние [popover] по умолчанию.
Примечание: Пример перехода для элемента <dialog> и его фона при отображении и скрытии можно найти на справочной странице <dialog> — см. раздел Переходы для элементов dialog.
Переходы при добавлении элементов в DOM и удалении из него
В этом примере есть кнопка, которая при нажатии добавляет новые элементы в контейнер <section>. Каждый элемент, в свою очередь, содержит вложенную кнопку, которая удаляет этот элемент при нажатии. Пример показывает, как использовать переходы для анимации элементов при добавлении в DOM и удалении из него.
HTML
<button>Create new column</button> <section></section>
JavaScript
JavaScript обеспечивает добавление и удаление элементов:
const btn = document.querySelector("button");
const sectionElem = document.querySelector("section");
btn.addEventListener("click", createColumn);
function randomBackground() {
function randomNum() {
return Math.floor(Math.random() * 255);
}
const baseColor = `${randomNum()} ${randomNum()} ${randomNum()}`;
return `linear-gradient(to right, rgb(${baseColor} / 0), rgb(${baseColor} / 0.5))`;
}
function createColumn() {
const divElem = document.createElement("div");
divElem.style.background = randomBackground();
const closeBtn = document.createElement("button");
closeBtn.textContent = "✖";
closeBtn.setAttribute("aria-label", "close");
divElem.append(closeBtn);
sectionElem.append(divElem);
closeBtn.addEventListener("click", () => {
divElem.classList.add("fade-out");
setTimeout(() => {
divElem.remove();
}, 1000);
});
}
При нажатии кнопки «Создать новый столбец» вызывается функция createColumn(). Она создаёт элемент <div> со случайно сгенерированным цветом фона и элемент <button> для закрытия <div>. Затем она добавляет <button> в <div>, а <div> — в контейнер <section>.
Затем с помощью addEventListener() мы добавляем обработчик события для кнопки закрытия. При её нажатии выполняются два действия:
- К
<div>добавляется классfade-out. Добавление класса запускает заданную для него анимацию исчезновения. - Через 1000 мс удаляется
<div>. МетодsetTimeout()откладывает удаление<div>из DOM (с помощьюElement.remove()) до окончания анимации.
CSS
Мы задаём свойство transition, которое анимирует opacity и scale каждого столбца при его добавлении и удалении:
html * {
box-sizing: border-box;
font-family: sans-serif;
}
body {
margin: 0;
display: flex;
flex-direction: column;
height: 100vh;
gap: 10px;
}
body > button {
margin: 10px 10px 0 10px;
}
section {
display: flex;
flex: 1;
gap: 10px;
margin: 10px;
}
div {
flex: 1;
border: 1px solid gray;
position: relative;
opacity: 1;
scale: 1 1;
transition:
opacity 0.7s,
scale 0.7s,
display 0.7s allow-discrete,
all 0.7s allow-discrete;
/* Equivalent to
transition: all 0.7s allow-discrete; */
}
/* Include after the `div` rule */
@starting-style {
div {
opacity: 0;
scale: 1 0;
}
}
.fade-out {
opacity: 0;
display: none;
scale: 1 0;
}
div > button {
font-size: 1.6rem;
background: none;
border: 0;
text-shadow: 2px 1px 1px white;
border-radius: 15px;
position: absolute;
top: 1px;
right: 1px;
cursor: pointer;
}
Чтобы анимировать opacity и scale каждого <div> при добавлении в DOM и обратить анимацию при удалении из DOM, мы:
- Задаём конечное состояние свойств, для которых нужен переход, в правиле
div { ... }. - Задаём начальное состояние, из которого будут переходить свойства, внутри блока
@starting-style. - Задаём анимацию исчезновения в правиле
.fade-out— JavaScript назначает этот класс элементам<div>при нажатии кнопок закрытия. Помимо задания конечных состоянийopacityиscale, мы также задаём для<div>свойствоdisplay: none— после удаления из интерфейса элементы должны сразу становиться недоступными. - Указываем список свойств
transitionвнутри правилаdiv { ... }, чтобы анимироватьopacity,scaleиdisplay. Обратите внимание, что дляdisplayзначениеtransition-behavior: allow-discreteтакже задаётся в сокращённой записи, чтобы это свойство анимировалось.
Результат
Итоговый результат выглядит так:
Спецификации
Совместимость с браузерами
| Настольные | Мобильные | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Chrome | Edge | Firefox | Opera | Safari | Chrome для Android | Firefox для Android | Opera для Android | Safari на iOS | Samsung Internet | WebView для Android | WebView на iOS | |
starting-style |
117 |
117 |
129 |
103 |
17.5 |
117 |
129 |
78 |
17.5 |
24.0 |
117 |
17.5 |
См. также
- Модуль CSS-переходы
overlaytransition-behaviorCSSStartingStyleRule- Четыре новые возможности CSS для плавной анимации появления и исчезновения на developer.chrome.com (2023)
© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/At-rules/@starting-style