Spec-Zone.ru › Web APIs

Использование API всплывающих окон

API всплывающих окон предоставляет разработчикам стандартный, согласованный и гибкий механизм для отображения содержимого всплывающих окон поверх другого контента страницы. Содержимое всплывающего окна может управляться декларативно с помощью атрибутов HTML или через JavaScript. Эта статья предоставляет подробное руководство по использованию всех его функций.

Создание декларативных всплывающих окон

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

<div id="mypopover" popover>Popover content</div>

Примечание: Установка атрибута popover без значения эквивалентна установке popover="auto".

Добавление этого атрибута скрывает элемент при загрузке страницы, установив display: none на нем. Для отображения/скрытия всплывающего окна необходимо добавить элементы управления. Вы можете установить <button> (или <input> типа type="button") в качестве кнопки управления всплывающим окном, присвоив ему атрибут popovertarget, значение которого должно быть идентификатором всплывающего окна для управления:

<button popovertarget="mypopover">Toggle the popover</button>
<div id="mypopover" popover>Popover content</div>

По умолчанию кнопка действует как переключатель — многократное нажатие на нее переключает всплывающее окно между отображением и скрытием.

Если вы хотите изменить это поведение, используйте атрибут popovertargetaction — он принимает значение "hide", "show", или "toggle". Например, для создания отдельных кнопок показа и скрытия можно сделать так:

<button popovertarget="mypopover" popovertargetaction="show">
  Show popover
</button>
<button popovertarget="mypopover" popovertargetaction="hide">
  Hide popover
</button>
<div id="mypopover" popover>Popover content</div>

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

Примечание: Если атрибут popovertargetaction опущен, "toggle" является значением по умолчанию для действия, которое будет выполнено кнопкой управления.

Когда всплывающее окно отображается, у него удаляется атрибут display: none и оно помещается в верхний слой, чтобы оно находилось поверх всего остального содержимого страницы.

Автоматическое состояние и «лёгкое закрытие»

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

  • Всплывающее окно может быть «легко закрыто» — это означает, что вы можете скрыть всплывающее окно, кликнув вне его.
  • Всплывающее окно также можно закрыть с помощью механизмов, специфичных для браузера, таких как нажатие клавиши Esc.
  • Обычно только одно всплывающее окно может быть отображено в одно время — отображение второго всплывающего окна, когда уже отображено одно, приведет к скрытию первого. Исключением из этого правила являются вложенные авто-всплывающие окна. Подробности см. в разделе Вложенные всплывающие окна.

Примечание: Всплывающие окна с автоматическим состоянием также закрываются при успешном вызове HTMLDialogElement.showModal() и Element.requestFullscreen() на других элементах документа. Однако имейте в виду, что вызов этих методов на уже отображаемом всплывающем окне приведет к ошибке, потому что такое поведение не имеет смысла для уже отображенного всплывающего окна. Тем не менее, вы можете вызвать их на элементе с атрибутом popover , который в данный момент не отображается.

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

Вы можете наблюдать описанное выше поведение в действии в нашем примере нескольких автоматических всплывающих окон (исходный код). Попробуйте закрыть всплывающие окна лёгким кликом, а затем посмотреть, что произойдёт, когда вы попытаетесь отобразить оба одновременно.

Использование ручного состояния всплывающего окна

Альтернативой автоматическому состоянию является ручное состояние, достигаемое установкой popover="manual" на элементе всплывающей подсказки:

<div id="mypopover" popover="manual">Popover content</div>

В этом состоянии:

  • Всплывающая подсказка не может быть закрыта «лёгким» способом, хотя декларативные кнопки показа/скрытия/переключения (как показано ранее) по-прежнему будут работать.
  • Несколько независимых всплывающих подсказок могут быть показаны одновременно.

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

Отображение всплывающих подсказок с помощью JavaScript

Вы также можете управлять всплывающими подсказками с помощью JavaScript API.

Свойство HTMLElement.popover может быть использовано для получения или установки атрибута popover. Это может быть использовано для создания всплывающей подсказки с помощью JavaScript, а также полезно для обнаружения функций. Например:

function supportsPopover() {
  return HTMLElement.prototype.hasOwnProperty("popover");
}

Аналогично:

  • HTMLButtonElement.popoverTargetElement и HTMLInputElement.popoverTargetElement обеспечивают эквивалент атрибуту popovertarget, позволяя вам настроить кнопку(ы) управления для всплывающей подсказки, хотя значение свойства является ссылкой на элемент всплывающей подсказки DOM для управления.
  • HTMLButtonElement.popoverTargetAction и HTMLInputElement.popoverTargetAction обеспечивают эквивалент глобальному HTML-атрибуту popovertargetaction, позволяя вам указать действие, выполняемое кнопкой управления.

Объединив эти три элемента, вы можете программно настроить всплывающую подсказку и её управляющую кнопку, как показано ниже:

const popover = document.getElementById("mypopover");
const toggleBtn = document.getElementById("toggleBtn");

const keyboardHelpPara = document.getElementById("keyboard-help-para");

const popoverSupported = supportsPopover();

if (popoverSupported) {
  popover.popover = "auto";
  toggleBtn.popoverTargetElement = popover;
  toggleBtn.popoverTargetAction = "toggle";
} else {
  toggleBtn.style.display = "none";
}

У вас также есть несколько методов для управления отображением и скрытием:

  • HTMLElement.showPopover() для отображения всплывающей подсказки.
  • HTMLElement.hidePopover() для скрытия всплывающей подсказки.
  • HTMLElement.togglePopover() для переключения всплывающей подсказки.

Например, вы можете предоставить возможность переключать всплывающую подсказку справки включение/выключение щелчком по кнопке или нажатием определённой клавиши на клавиатуре. Первое можно реализовать декларативно, или же можно сделать это с помощью JavaScript, как показано выше.

Для второго можно создать обработчик событий, который программно обрабатывает две отдельные клавиши — одну для открытия всплывающей подсказки и другую для её закрытия:

document.addEventListener("keydown", (event) => {
  if (event.key === "h") {
    if (popover.matches(":popover-open")) {
      popover.hidePopover();
    }
  }

  if (event.key === "s") {
    if (!popover.matches(":popover-open")) {
      popover.showPopover();
    }
  }
});

В этом примере используется Element.matches() для программно проверки, отображается ли в настоящее время всплывающая подсказка. Псевдокласс :popover-open соответствует только всплывающим подсказкам, которые в настоящее время отображаются. Это важно, чтобы избежать ошибок, которые возникают при попытке отобразить уже отображаемую всплывающую подсказку или скрыть уже скрытую.

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

document.addEventListener("keydown", (event) => {
  if (event.key === "h") {
    popover.togglePopover();
  }
});

Посмотрите наш пример переключения интерфейса справки (исходный код), чтобы увидеть свойства всплывающей подсказки JavaScript, обнаружение функций и метод togglePopover() в действии.

Вложенные всплывающие подсказки

Есть исключение из правила, что нельзя отображать несколько автоматических всплывающих подсказок одновременно — когда они вложены друг в друга. В таких случаях нескольким всплывающим подсказкам разрешается быть открытыми одновременно из-за их взаимосвязи. Эта модель поддерживается, чтобы обеспечить такие варианты использования, как вложенные меню всплывающих подсказок.

Существует три разных способа создания вложенных всплывающих подсказок:

  1. Прямые дочерние элементы DOM:

    <div popover>
      Parent
      <div popover>Child</div>
    </div>
    
  2. Через вызов/элементы управления:

    <div popover>
      Parent
      <button popovertarget="foo">Click me</button>
    </div>
    
    <div popover id="foo">Child</div>
    
  3. Через атрибут anchor:

    <div popover id="foo">Parent</div>
    
    <div popover anchor="foo">Child</div>
    

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

Стиль всплывающих подсказок

API всплывающей подсказки содержит некоторые связанные CSS-функциональные возможности, которые стоит рассмотреть.

Что касается стилизации самой всплывающей подсказки, вы можете выбрать все всплывающие подсказки с помощью простого селектора атрибутов ([popover]), или вы можете выбрать всплывающие подсказки, которые отображаются, используя новый псевдокласс — :popover-open.

При рассмотрении первых нескольких примеров, связанных в начале статьи, вы, возможно, заметили, что всплывающие подсказки появляются посередине области просмотра. Это стандартная стилизация, достигаемая следующим образом в таблице стилей браузера:

[popover] {
  position: fixed;
  inset: 0;
  width: fit-content;
  height: fit-content;
  margin: auto;
  border: solid;
  padding: 0.25em;
  overflow: auto;
  color: CanvasText;
  background-color: Canvas;
}

Чтобы переопределить стандартные стили и разместить всплывающую подсказку в другом месте области просмотра, необходимо переопределить вышеуказанные стили, например, так:

:popover-open {
  width: 200px;
  height: 100px;
  position: absolute;
  inset: unset;
  bottom: 5px;
  right: 5px;
  margin: 0;
}

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

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

::backdrop {
  backdrop-filter: blur(3px);
}

Посмотрите наш пример размытия фона всплывающей подсказки (исходный код), чтобы понять, как это отображается.

Анимация всплывающих подсказок

Всплывающие подсказки устанавливаются в состояние display: none; при скрытии и в состояние display: block; при отображении, а также удаляются из / добавляются в верхний слой и дерево доступности. Поэтому, чтобы всплывающие подсказки анимировались, свойство display должно быть анимируемым. Поддерживающие браузеры анимируют display с вариантом типа анимации дискретной анимации. В частности, браузер будет переключаться между none и другим значением display, чтобы анимированное содержимое отображалось на протяжении всей анимации. Таким образом, например:

  • При анимации display от none до block (или другого видимого display значения), значение переключится на block в 0% процентах длительности анимации, чтобы оно оставалось видимым на протяжении всей анимации.
  • При анимации display от block (или другого видимого display значения) до none, значение переключится на none в 100% процентах длительности анимации, чтобы оно оставалось видимым на протяжении всей анимации.

Примечание: При анимации с использованием CSS-переходов, transition-behavior: allow-discrete необходимо установить, чтобы включить указанное поведение. При анимации с использованием CSS-анимаций, указанное поведение доступно по умолчанию; эквивалентный шаг не требуется.

Переход всплывающей подсказки

При анимации всплывающих подсказок с помощью CSS-переходов необходимы следующие функции:

@starting-style псевдоправило

Обеспечивает набор начальных значений для свойств всплывающей подсказки, от которых происходит переход при первом отображении. Это необходимо для предотвращения неожиданного поведения. По умолчанию CSS-переходы происходят только тогда, когда свойство изменяется от одного значения к другому на видимом элементе; они не срабатывают при первом обновлении стиля элемента или при изменении типа display с none на другой тип.

display свойство

Добавьте display в список переходов, чтобы всплывающая подсказка оставалась видимой (display: block или другим видимым значением display ) на протяжении всего перехода, гарантируя видимость других переходов.

overlay свойство

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

transition-behavior свойство

Установите transition-behavior: allow-discrete для переходов display и overlay (или для сокращённого свойства transition) для активации дискретных переходов этих двух свойств, которые по умолчанию не анимируются.

Давайте посмотрим на пример, чтобы вы увидели, как это выглядит:

HTML

HTML содержит элемент <div>, объявленный как всплывающая подсказка посредством глобального атрибута HTML popover, и элемент <button>, назначенный для управления отображением всплывающей подсказки:

<button popovertarget="mypopover">Show the popover</button>
<div popover="auto" id="mypopover">I'm a Popover! I should animate.</div>

CSS

Два свойства всплывающей подсказки, которые мы хотим анимировать, это opacity и transform. Мы хотим, чтобы всплывающая подсказка поблескивала при горизонтальном увеличении или уменьшении. Для этого мы устанавливаем начальное состояние этих свойств для скрытого состояния элемента всплывающей подсказки (выбранного с помощью [popover] селектора атрибута) и конечное состояние для отображаемого состояния всплывающей подсказки (выбранного с помощью псевдокласса :popover-open). Мы также используем свойство transition, чтобы определить анимируемые свойства и продолжительность анимации при отображении или скрытии всплывающей подсказки.

html {
  font-family: Arial, Helvetica, sans-serif;
}

/* Transition for the popover itself */

[popover]:popover-open {
  opacity: 1;
  transform: scaleX(1);
}

[popover] {
  font-size: 1.2rem;
  padding: 10px;

  /* Final state of the exit animation */
  opacity: 0;
  transform: scaleX(0);

  transition:
    opacity 0.7s,
    transform 0.7s,
    overlay 0.7s allow-discrete,
    display 0.7s allow-discrete;
  /* Equivalent to
  transition: all 0.7s allow-discrete; */
}

/* Needs to be after the previous [popover]:popover-open rule
to take effect, as the specificity is the same */
@starting-style {
  [popover]:popover-open {
    opacity: 0;
    transform: scaleX(0);
  }
}

/* Transition for the popover's backdrop */

[popover]::backdrop {
  background-color: rgb(0 0 0 / 0%);
  transition:
    display 0.7s allow-discrete,
    overlay 0.7s allow-discrete,
    background-color 0.7s;
  /* Equivalent to
  transition: all 0.7s allow-discrete; */
}

[popover]:popover-open::backdrop {
  background-color: rgb(0 0 0 / 25%);
}

/* The nesting selector (&) cannot represent pseudo-elements
so this starting-style rule cannot be nested */

@starting-style {
  [popover]:popover-open::backdrop {
    background-color: rgb(0 0 0 / 0%);
  }
}

Как обсуждалось ранее, мы также:

  • Установили начальное состояние transition внутри блока @starting-style.
  • Добавили display в список анимируемых свойств, чтобы анимируемый элемент оставался видимым (установленным в значение display: block) на протяжении всего процесса показа и скрытия всплывающей подсказки. Без этого анимация скрытия не отображалась бы, в результате всплывающая подсказка просто исчезала бы.
  • Добавили overlay в список анимируемых свойств, чтобы гарантировать отсрочку удаления элемента с верхнего уровня до завершения анимации. Эффект этого может быть незаметен для простых анимаций, таких как эта, но в более сложных случаях опускание этого свойства может привести к удалению элемента из перекрытия до завершения перехода.
  • Установили allow-discrete для обоих свойств в указанных переходах, чтобы активировать дискретные переходы.

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

Результат

Код отображается следующим образом:

Примечание: Поскольку всплывающие подсказки меняются с display: none на display: block каждый раз при отображении, анимация перехода всплывающей подсказки из @starting-style стилей в [popover]:popover-open стили происходит каждый раз при появлении элемента. При закрытии всплывающей подсказки она переходит из состояния [popover]:popover-open в стандартное состояние [popover].

В таких случаях переход стилей при появлении и скрытии может отличаться. Смотрите пример Демонстрация использования начальных стилей для доказательства этого.

Анимация всплывающей подсказки с ключевыми кадрами

При анимации всплывающей подсказки с помощью анимации CSS с ключевыми кадрами следует учесть некоторые различия:

  • Вы не предоставляете @starting-style; вы включаете значения "к" и "от" display в ключевых кадрах.
  • Вы не явно включаете дискретную анимацию; нет эквивалента allow-discrete внутри ключевых кадров.
  • Вам также не нужно устанавливать overlay внутри ключевых кадров; анимация display обрабатывает анимацию всплывающей подсказки от показа до скрытия.

Давайте рассмотрим пример.

HTML

HTML содержит элемент <div>, объявленный как всплывающая подсказка, и элемент <button>, назначенный элементом управления отображением всплывающей подсказки:

<button popovertarget="mypopover">Show the popover</button>
<div popover="auto" id="mypopover">I'm a Popover! I should animate.</div>

CSS

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

html {
  font-family: Arial, Helvetica, sans-serif;
}

[popover] {
  font-size: 1.2rem;
  padding: 10px;
  animation: fade-out 0.7s ease-out;
}

[popover]:popover-open {
  animation: fade-in 0.7s ease-out;
}

[popover]:popover-open::backdrop {
  animation: backdrop-fade-in 0.7s ease-out forwards;
}

/* Animation keyframes */

@keyframes fade-in {
  0% {
    opacity: 0;
    transform: scaleX(0);
  }

  100% {
    opacity: 1;
    transform: scaleX(1);
  }
}

@keyframes fade-out {
  0% {
    opacity: 1;
    transform: scaleX(1);
    /* display needed on the closing animation to keep the popover
    visible until the animation ends */
    display: block;
  }

  100% {
    opacity: 0;
    transform: scaleX(0);
    /* display: none not required here because it is the default value
    for a closed popover, but including it so the behavior is clear */
    display: none;
  }
}

@keyframes backdrop-fade-in {
  0% {
    background-color: rgb(0 0 0 / 0%);
  }

  100% {
    background-color: rgb(0 0 0 / 25%);
  }
}

Результат

Код отображается следующим образом:

© 2005–2024 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/API/Popover_API/Using

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API