display: none без единой строчки JS. Речь про @starting-style и transition-behavior: allow-discrete.---
## Проблема
Раньше нельзя было плавно показать попап, который скрыт через
display: none (стандарт для popover/dialog в закрытом состоянии). Браузер не мог найти стартовое состояние для перехода. Результат — либо мгновенное появление, либо костыли с JS и реквайрами.## Решение
**Шаг 1.
display и overlay участвуют в transition**Свойство
display — дискретное. Чтобы переход не сработал мгновенно, нужно разрешить дискретные значения анимироваться:transition-behavior: allow-discrete;
Если указать это в
transition для display, то браузер «перекидывает» значение с none на block в **начале** анимации появления и в **конце** анимации исчезновения. Элемент для закрывающегося попапа остаётся видимым до конца анимации, а потом получает display: none.Для попапов важно ещё и
overlay — отключает верхний слой (top layer) только после завершения анимации.**Шаг 2.
@starting-style — стили «до старта»**Когда браузер переключает
display с none, у элемента нет предыдущего состояния, от которого можно анимировать. @starting-style задаёт стартовые стили:.popover {
opacity: 0;
transform: translateY(-10px);
transition:
opacity 0.3s ease,
transform 0.3s ease,
display 0.3s allow-discrete,
overlay 0.3s allow-discrete;
}
.popover:popover-open {
opacity: 1;
transform: translateY(0);
}
@starting-style {
.popover:popover-open {
opacity: 0;
transform: translateY(-10px);
}
}## Как это работает
- При открытии:
@starting-style мгновенно применяет opacity: 0, затем срабатывает переход к opacity: 1.- При закрытии: обычные стили возвращают попап к
opacity: 0, а display: none и уход из top layer (overlay) применяются только в конце transition.## Важные нюансы
1. Без
allow-discrete display переключится мгновенно, анимация исчезновения не будет.2.
overlay нужно указывать именно для элементов в top layer (popover, dialog). Обычные выпадашки могут обойтись без него.3. Поддержка: все современные браузеры, включая Safari 17.5+ и Chrome 117+. Работает и для
<dialog>, и для [popover].## Минимальный пример
<button popovertarget="tip">Показать</button>
<div popover id="tip">Подсказка</div>
#tip {
opacity: 0;
transform: scale(0.95);
transition:
opacity 0.2s ease,
transform 0.2s ease,
display 0.2s allow-discrete,
overlay 0.2s allow-discrete;
}
#tip:popover-open {
opacity: 1;
transform: scale(1);
}
@starting-style {
#tip:popover-open {
opacity: 0;
transform: scale(0.95);
}
}Теперь никакого JS для анимации попапов — только чистый CSS. Удобно, когда нужно скрыть логику анимации из бандла и убрать хрупкие кодушки с анимациями через классы.