Можно ли анимировать свойства opacity, visibility и display
Что проверяют
Знаете ли вы, какие свойства интерполируются плавно, а какие дискретно, и в курсе ли новых возможностей CSS для display. Следом обычно просят написать плавное появление и скрытие модалки без JavaScript и объяснить, почему элемент с opacity: 0 всё ещё кликается.
Как отвечать
Разберите три свойства по отдельности:
- opacity: анимируется плавно, число от 0 до 1. Вместе с
transformэто самые дешёвые свойства: браузер обрабатывает их на этапе композитинга, без пересчёта раскладки и перерисовки; - visibility: анимируется, но дискретно, и с полезной особенностью. Если одно из крайних значений
visible, элемент остаётся видимым на всём протяжении перехода. При скрытии он переключается вhiddenв самом конце, при показе становится видимым сразу. Поэтому связкаtransition: opacity .3s, visibility .3sдаёт честное затухание, после которого элемент недоступен для клика и фокуса; - display: долго не анимировался вовсе. Сейчас переход до
display: noneи обратно работает черезtransition-behavior: allow-discrete, а начальное состояние при появлении задаётся в@starting-style. С 2024 года это поддерживают все основные браузеры.
Пример для модалки: transition: opacity .3s, display .3s allow-discrete, в @starting-style прописан opacity: 0. При закрытии display переключится в none только после окончания затухания. Для закрытия <dialog> и поповеров в тот же список добавляют overlay, чтобы элемент не покинул верхний слой раньше конца анимации.
Где спотыкаются
Говорят, что visibility не анимируется. Он анимируется дискретно, и именно это делает его полезным в паре с opacity.
Прячут элемент одной opacity: 0. Он остаётся в раскладке, ловит клики и получает фокус с клавиатуры. Нужен visibility: hidden, атрибут inert или хотя бы pointer-events: none.
Пишут allow-discrete, но забывают @starting-style, и анимация появления не играет: у элемента, который только что вышел из display: none, нет предыдущего стиля, от которого можно стартовать.