Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Как анимировать открытие диалога или поповера

Короткий ответ

Опишите открытое состояние, начальное через @starting-style и разрешите анимировать display:

<style>
  dialog { opacity: 0; translate: 0 20px;
    transition: opacity 0.3s, translate 0.3s, display 0.3s allow-discrete, overlay 0.3s allow-discrete; }
  dialog[open] { opacity: 1; translate: 0 0; }
  @starting-style { dialog[open] { opacity: 0; translate: 0 20px; } }
</style>
 
<button onclick="hello.showModal()">Open</button>
<dialog id="hello">
  <p>Hello! This window fades in.</p>
  <form method="dialog"><button>Close</button></form>
</dialog>

Как это работает:

  • @starting-style задаёт стиль, с которого элемент начинает переход в момент появления. Без него браузеру не от чего анимировать: элемент был display: none.
  • allow-discrete у display откладывает скрытие до конца перехода, поэтому закрытие тоже плавное.
  • overlay держит диалог в верхнем слое, пока идёт анимация закрытия.

Поповер

Для popover всё так же, только открытое состояние — псевдокласс :popover-open:

<style>
  [popover] { opacity: 0; scale: 0.9;
    transition: opacity 0.25s, scale 0.25s, display 0.25s allow-discrete, overlay 0.25s allow-discrete; }
  [popover]:popover-open { opacity: 1; scale: 1; }
  @starting-style { [popover]:popover-open { opacity: 0; scale: 0.9; } }
</style>
 
<button popovertarget="menu">Menu</button>
<div id="menu" popover>Settings · Profile · Log out</div>

Затемнение фона

::backdrop анимируется так же: задайте ему прозрачный фон по умолчанию, полупрозрачный для dialog[open]::backdrop, тот же transition и начальное состояние в @starting-style.

Частая ошибка

Ставить @starting-style раньше правила для открытого состояния с той же специфичностью. Блок @starting-style не повышает специфичность, и правило ниже его перебивает — анимация входа пропадает. Пишите @starting-style после основных стилей, как в примерах. В браузерах без поддержки окно просто откроется без анимации.

Функции из этого ответа

  • @starting-style — Задаёт стили, с которых элемент начинает при первом появлении, чтобы `transition` анимировал его появление.
  • transition-behavior — Разрешает переходы дискретных свойств вроде `display` и `overlay`, чтобы элемент успел плавно исчезнуть, прежде чем пропасть.
  • <dialog> — Диалоговое окно; модальное открывается методом `showModal()` и блокирует остальную страницу.
  • popover — Превращает элемент во всплывающий слой поверх страницы — без JavaScript.
  • transition — Плавно анимирует изменение свойства от старого значения к новому.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.