Эта статья — перевод оригинальной статьи "Introducing the popover API".

Также я веду телеграм канал “Frontend по-флотски”, где рассказываю про интересные вещи из мира разработки интерфейсов.

Вступление

Всплывающие окна встречаются в вебе повсеместно. Вы можете увидеть их в меню, переключателях и диалоговых окнах, которые могут проявляться в виде настроек учетной записи, виджетов раскрытия информации и предварительных просмотров карточек товаров. Несмотря на распространенность этих компонентов, их создание в браузерах все еще остается на удивление громоздким. Вам нужно добавить скрипты для управления фокусом, состояниями открытия и закрытия, доступные хуки для компонентов, привязки к клавиатуре для входа и выхода из опыта, и это все еще до того, как вы начнете создавать полезную, уникальную, основную функциональность вашего всплывающего окна.

Чтобы решить эту проблему, в браузеры приходит новый набор декларативных HTML API для создания всплывающих окон, начиная с popover API в Chromium 114.

Атрибут popover

Вместо того чтобы самостоятельно управлять всеми этими сложностями, вы можете позволить браузеру справиться с ними с помощью атрибута popover и последующего набора функций. Возможности HTML popover:

  • Продвижение на верхний слой. Всплывающие окна будут отображаться на отдельном слое над остальной частью страницы, поэтому вам не придется возиться с z-индексом.

  • Функция закрытия по клику вне контента. При нажатии за пределами области всплывающего окна всплывающее окно закрывается и возвращается фокус.

  • Управление фокусом по умолчанию. При открытии всплывающего окна происходит переключение фокуса на контент внутри всплывающего окна.

  • Доступные клавиатурные привязки. Нажатие клавиши esc закрывает всплывающее окно и возвращает фокус.

  • Доступные привязки компонентов. Семантическое соединение элемента всплывающего окна с триггером всплывающего окна.

Теперь вы можете создавать всплывающие окна со всеми этими функциями без использования JavaScript. Для создания базового всплывающего окна необходимы три вещи:

  1. Атрибут popover на элементе, содержащем всплывающее окно.

  2. id на элементе, содержащее всплывающее окно.

  3. 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.

CodePen

Это всплывающее окно можно использовать для показа дополнительной информации или в качестве виджета.

Умолчания и переопределения

По умолчанию, как в предыдущем фрагменте кода, настройка всплывающего окна с помощью 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>

CodePen

Автоматические и ручные всплывающие окна

Использование атрибута popover само по себе является сокращением для popover="auto". При открытии popover по умолчанию принудительно закрывает другие автоматические popover, за исключением popover-предков. Его можно закрыть с помощью клика вне его контента или кнопки закрытия.

С другой стороны, установка popover=manual создает другой тип всплывающего окна: ручное всплывающее окно. Они не принудительно закрывают элементы другого типа и не закрываются с помощью клика вне его контента. Вы должны закрыть их с помощью таймера или явного действия закрытия. Типы всплывающих окон, подходящие для popover=manual, - это элементы, которые появляются и исчезают, но не должны влиять на остальную часть страницы, например, уведомление.

CodePen

Если вы изучите демонстрационный пример выше, то увидите, что щелчок за пределами области всплывающего окна не приводит к отключению подсветки всплывающего окна. Кроме того, если были открыты другие всплывающие окна, они не закрываются.

Чтобы рассмотреть различия:

Всплывающие окна с popover=auto:

  • При открытии принудительно закрывает другие всплывающие окна.

  • Можно закрыть по клику вне контента.

Всплывающие окна с popover=manual:

  • Не закрывайте принудительно элементы любого другого типа.

  • Не закрываются по клику вне контента. Их нужно закрывать используя таймер или явное действие закрытия.

Стилизация всплывающих окон

До этого вы узнали о базовых всплывающих окнах в HTML. Но есть также несколько приятных возможностей стилизации, которые поставляются с popover. Одна из них - возможность стилизовать ::backdrop.

В автоматических всплывающих окнах это слой, расположенный непосредственно под верхним слоем (на котором расположено всплывающее окно), который находится над остальной частью страницы. В следующем примере ::backdrop имеет полупрозрачный цвет:

#size-guide::backdrop {
  background: rgb(190 190 190 / 50%);
}

CodePen

По умолчанию всплывающие окна имеют border в 2px и располагаются в центре интерфейса, но они полностью настраиваются! Вы можете изменить стиль всплывающего окна, как и любого другого элемента HTML: изменить его размер, фон, положение на странице и так далее.

Разница между всплывающим и диалоговым окном

Важно отметить, что атрибут popover не обеспечивает семантику сам по себе. И хотя теперь вы можете создавать модальные диалоговые окна, используя popover="auto", между ними есть несколько ключевых различий:

Элемент dialog, открытый с помощью dialog.showModal, представляет собой опыт, который требует явного взаимодействия с пользователем для закрытия модалки. Popover поддерживает закрытие по клику вне контента. Элемент dialog - нет. Dialog делает остальную часть страницы неактивной, popover этого нет.

CodePen

Приведенная выше демонстрация представляет собой семантический 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

Реализация этой функции в настоящее время находится в процессе разработки, но перейдите к демонстрации 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;
}

CodePen

Теперь у вас есть полнофункциональное всплывающее меню, которое привязано к кнопке переключения и обладает всеми встроенными функциями всплывающего меню, без необходимости использования JavaScript!

Есть еще более захватывающие новые возможности привязки CSS, такие как выражение @try для изменения положения меню в зависимости от доступного пространства области просмотра. Эта реализация зависит от случая. Изучите демонстрацию Codepen выше с включенным флагом #experimental-web-platform-features в Chrome Canary, чтобы узнать больше.

Заключение

Popover API - это первый шаг в серии новых возможностей, призванных облегчить управление созданием веб-приложений и сделать их более доступными по умолчанию. Мне не терпится увидеть, как вы будете использовать всплывающие окна!

Комментарии (2)


  1. microspace
    25.05.2023 04:30

    React portal станет не нужен?


  1. john_samilin
    25.05.2023 04:30
    +1

    Dialog вообще-то нормально по клику вне контента закрывается