Эта статья — перевод оригинальной статьи "Introducing the popover API".
Также я веду телеграм канал “Frontend по-флотски”, где рассказываю про интересные вещи из мира разработки интерфейсов.
Вступление
Всплывающие окна встречаются в вебе повсеместно. Вы можете увидеть их в меню, переключателях и диалоговых окнах, которые могут проявляться в виде настроек учетной записи, виджетов раскрытия информации и предварительных просмотров карточек товаров. Несмотря на распространенность этих компонентов, их создание в браузерах все еще остается на удивление громоздким. Вам нужно добавить скрипты для управления фокусом, состояниями открытия и закрытия, доступные хуки для компонентов, привязки к клавиатуре для входа и выхода из опыта, и это все еще до того, как вы начнете создавать полезную, уникальную, основную функциональность вашего всплывающего окна.
Чтобы решить эту проблему, в браузеры приходит новый набор декларативных HTML API для создания всплывающих окон, начиная с popover API в Chromium 114.
Атрибут popover
Вместо того чтобы самостоятельно управлять всеми этими сложностями, вы можете позволить браузеру справиться с ними с помощью атрибута popover и последующего набора функций. Возможности HTML popover:
Продвижение на верхний слой. Всплывающие окна будут отображаться на отдельном слое над остальной частью страницы, поэтому вам не придется возиться с z-индексом.
Функция закрытия по клику вне контента. При нажатии за пределами области всплывающего окна всплывающее окно закрывается и возвращается фокус.
Управление фокусом по умолчанию. При открытии всплывающего окна происходит переключение фокуса на контент внутри всплывающего окна.
Доступные клавиатурные привязки. Нажатие клавиши esc закрывает всплывающее окно и возвращает фокус.
Доступные привязки компонентов. Семантическое соединение элемента всплывающего окна с триггером всплывающего окна.
Теперь вы можете создавать всплывающие окна со всеми этими функциями без использования JavaScript. Для создания базового всплывающего окна необходимы три вещи:
Атрибут
popover
на элементе, содержащем всплывающее окно.id
на элементе, содержащее всплывающее окно.popovertarget
со значениемid
всплывающего окна на элементе, который открывает всплывающее окно.
<button popovertarget="my-popover"> Open Popover </button>
<div id="my-popover" popover>
<p>I am a popover with more information.<p>
</div>
Теперь у вас есть полностью функциональный базовый popover.
Это всплывающее окно можно использовать для показа дополнительной информации или в качестве виджета.
Умолчания и переопределения
По умолчанию, как в предыдущем фрагменте кода, настройка всплывающего окна с помощью popovertarget
означает, что кнопка или элемент, который открывает всплывающее окно, будет переключать его на открытое и закрытое состояния. Однако вы ещё можете создавать явные всплывающие окна с помощью popovertargetaction
. Это отменяет действие переключения по умолчанию. Опции popovertargetaction
включают:
popovertargetaction="show"
: Показывает всплывающее окно. popovertargetaction="hide"
: Скрывает всплывающее окно.
Используя popovertargetaction="hide"
, вы можете создать кнопку "закрыть" внутри всплывающего окна, как в следующем фрагменте:
<button popovertarget="my-popover" popovertargetaction="hide">
<span aria-hidden=”true”>❌</span>
<span class="sr-only">Close</span>
</button>
Автоматические и ручные всплывающие окна
Использование атрибута popover
само по себе является сокращением для popover="auto"
. При открытии popover
по умолчанию принудительно закрывает другие автоматические popover, за исключением popover-предков. Его можно закрыть с помощью клика вне его контента или кнопки закрытия.
С другой стороны, установка popover=manual
создает другой тип всплывающего окна: ручное всплывающее окно. Они не принудительно закрывают элементы другого типа и не закрываются с помощью клика вне его контента. Вы должны закрыть их с помощью таймера или явного действия закрытия. Типы всплывающих окон, подходящие для popover=manual
, - это элементы, которые появляются и исчезают, но не должны влиять на остальную часть страницы, например, уведомление.
Если вы изучите демонстрационный пример выше, то увидите, что щелчок за пределами области всплывающего окна не приводит к отключению подсветки всплывающего окна. Кроме того, если были открыты другие всплывающие окна, они не закрываются.
Чтобы рассмотреть различия:
Всплывающие окна с popover=auto
:
При открытии принудительно закрывает другие всплывающие окна.
Можно закрыть по клику вне контента.
Всплывающие окна с popover=manual
:
Не закрывайте принудительно элементы любого другого типа.
Не закрываются по клику вне контента. Их нужно закрывать используя таймер или явное действие закрытия.
Стилизация всплывающих окон
До этого вы узнали о базовых всплывающих окнах в HTML. Но есть также несколько приятных возможностей стилизации, которые поставляются с popover
. Одна из них - возможность стилизовать ::backdrop
.
В автоматических всплывающих окнах это слой, расположенный непосредственно под верхним слоем (на котором расположено всплывающее окно), который находится над остальной частью страницы. В следующем примере ::backdrop
имеет полупрозрачный цвет:
#size-guide::backdrop {
background: rgb(190 190 190 / 50%);
}
По умолчанию всплывающие окна имеют border в 2px и располагаются в центре интерфейса, но они полностью настраиваются! Вы можете изменить стиль всплывающего окна, как и любого другого элемента HTML: изменить его размер, фон, положение на странице и так далее.
Разница между всплывающим и диалоговым окном
Важно отметить, что атрибут popover не обеспечивает семантику сам по себе. И хотя теперь вы можете создавать модальные диалоговые окна, используя popover="auto", между ними есть несколько ключевых различий:
Элемент dialog
, открытый с помощью dialog.showModal
, представляет собой опыт, который требует явного взаимодействия с пользователем для закрытия модалки. Popover поддерживает закрытие по клику вне контента. Элемент dialog - нет. Dialog делает остальную часть страницы неактивной, popover этого нет.
Приведенная выше демонстрация представляет собой семантический dialog
с поведением popover
. Это означает, что остальная часть страницы является неактивной и что всплывающее диалоговое окно получает поведение закрытие по клику вне контента. Вы можете создать элемент dialog
с поведением popover
, используя следующий код:
<button popovertarget="candle-01">
Quick Shop
</button>
<dialog popover id="candle-01">
<button class="close-btn" popovertarget="candle-01" popovertargetaction="hide">...</button>
<div class="product-preview-container">
...
</div>
</dialog>
В настоящее время группа WhatWG и сообщество OpenUI обсуждают возможность открытия диалогового элемента с эргономикой HTML. Это было бы похоже на popover, но сохранило бы функции диалога, перечисленные ранее, например, делая остальную часть страницы неактивной. Следите за этими группами, чтобы узнать о будущем popover
, dialog
и новых элементов, таких как selectmenu
.
Скоро появится
Интерактивный вход и выход
Возможность анимировать свойства, включая анимирование display: none
и анимирование верхнего слоя, пока недоступна в браузерах. Однако они запланированы в ближайшей версии Chromium, которая выйдет сразу после этого релиза.
С возможностью анимировать свойства, а также используя :popover-open
и @starting-style
, вы сможете установить стили до и после изменения, чтобы обеспечить плавные переходы при открытии и закрытии всплывающих окон. Возьмем предыдущий пример. Анимация при открытии и закрытии выглядит намного плавнее:
Реализация этой функции в настоящее время находится в процессе разработки, но перейдите к демонстрации codepen для получения последней версии синтаксиса и опробуйте ее с включенным флагом #experimental-web-platform-features в Chrome Canary.
Позиционирование якоря
Всплывающие окна отлично подходят для размещения оповещения, модального окна или уведомления в зависимости от области просмотра. Но всплывающие окна также полезны для меню, всплывающих подсказок и других элементов, которые необходимо позиционировать относительно других элементов. Здесь на помощь приходит CSS anchoring.
В следующем демонстрационном примере меню используется popover API вместе с CSS anchor positioning для того, чтобы всплывающее меню #menu-items
всегда было привязано к своему триггеру переключения - кнопке #menu-toggle
.
Настройка якорей аналогична настройке всплывающих окон:
<button id="menu-toggle" popovertarget="menu-items">
Open Menu
</button>
<ul id="menu-items" popover anchor="menu-toggle">
<li class="item">...</li>
<li class="item">...</li>
</ul>
Вы устанавливаете якорь, присваивая ему id
(в данном примере #menu-toggle
), а затем используете anchor="menu-toggle"
для соединения двух элементов. Теперь вы можете использовать anchor()
для стилизации всплывающего меню. Центрированное всплывающее меню может быть оформлено следующим образом:
#menu-items {
bottom: calc(anchor(bottom));
left: anchor(center);
translate: -50% 0;
}
Теперь у вас есть полнофункциональное всплывающее меню, которое привязано к кнопке переключения и обладает всеми встроенными функциями всплывающего меню, без необходимости использования JavaScript!
Есть еще более захватывающие новые возможности привязки CSS, такие как выражение @try
для изменения положения меню в зависимости от доступного пространства области просмотра. Эта реализация зависит от случая. Изучите демонстрацию Codepen выше с включенным флагом #experimental-web-platform-features в Chrome Canary, чтобы узнать больше.
Заключение
Popover API - это первый шаг в серии новых возможностей, призванных облегчить управление созданием веб-приложений и сделать их более доступными по умолчанию. Мне не терпится увидеть, как вы будете использовать всплывающие окна!
microspace
React portal станет не нужен?