Living Standard — Last Updated 9 January 2023
popover
attributeAll HTML elements may have the popover
content attribute set. When specified, the element
won't be rendered until it becomes shown, at which point it will be rendered on top of other page
content.
The popover
attribute is an enumerated
attribute. The following table lists the states for this attribute:
State | Keywords | Description |
---|---|---|
Auto state | auto | Closes other popovers when opened; has light dismiss. |
The empty string | ||
Manual state | manual | Does not close other popovers; does not light dismiss. |
The attribute may be omitted. The invalid value default is the manual state. The missing value default is the no popover state.
The popover
IDL attribute
must reflect the popover attribute, limited
to only known values.
Every HTML element has a popover visibility state, initially , with these potential values:
hidden
showing
The Document
has an auto popover list, which is a list,
initially empty.
The Document
has a popover pointerdown target, which is an HTML element or null, initially null.
Every HTML element has a popover invoker, which is an HTML element or null, initially set to null.
The following attribute change steps are used for all HTML elements:
If namespace is not null, then return.
If localName is not popover
, then
return.
If oldValue and value are in different states, then run the hide popover algorithm given element, true, false, and false.
element.showPopover()
popover
attribute is in the auto state, then this will also close all other auto popovers unless they are an ancestor of
element according to the topmost popover ancestor algorithm.element.hidePopover()
display: none
to it.element.togglePopover()
The showPopover()
method steps are:
Run show popover given this and true.
To show popover, given an HTML element element and a boolean throwExceptions:
If the result of running check popover validity given element and false is false, then:
Assert: throwExceptions is true.
Throw an "InvalidStateError
"
DOMException
.
Assert: element is not in element's node document's top layer.
If the result of firing an event named beforetoggle
, using BeforeToggleEvent
, with the
cancelable
attribute initialized to true, the currentState
attribute initialized to "closed
", and the newState
attribute initialized to "open
" at element is false, then
return.
If the result of running check popover validity given element and false is false:
If throwExceptions is true, then throw an
"InvalidStateError
" DOMException
.
Otherwise, return.
Check popover validity is called again because firing the beforetoggle
event could have disconnected this element or
changed its popover
attribute.
Let document be element's node document.
Let shouldRestoreFocus be false.
If element's popover
attribute is in the auto state, then:
Let originalType be the value of element's popover
attribute.
Let ancestor be the result of running the topmost popover ancestor algorithm given element.
Run hide all popovers until given ancestor, false, and false.
If originalType is not equal to the value of element's popover
attribute, or if the result of running check
popover validity given element and false is false:
If throwExceptions is true, then throw an
"InvalidStateError
" DOMException
.
Otherwise, return.
Check popover validity is called again because running hide all popovers until above could have fired the
beforetoggle
event, and an event handler could have
disconnected this element or called showPopover()
on
this element.
If the result of running topmost auto popover on document is null, then set shouldRestoreFocus to true.
This ensures that focus is returned to the previously-focused element only for the first popover in a stack.
Add element to document's auto popover list.
Set element's previously focused element to null.
Let originallyFocusedElement be document's focused area of the document's DOM anchor.
Add element to document's top layer.
Set element's popover visibility state to showing.
Run the popover focusing steps given element.
If shouldRestoreFocus is true and element's popover
attribute is not in the no popover state, then set element's
previously focused element to originallyFocusedElement.
The hidePopover()
method steps are:
Run the hide popover algorithm given this, true, false, and true.
To hide a popover given an HTML element element, a boolean focusPreviousElement, a boolean dontFireBeforetoggle, and a boolean throwExceptions:
If the result of running check popover validity given element and true is false:
If throwExceptions is true, then throw an
"InvalidStateError
" DOMException
.
Otherwise, return.
Let document be element's node document.
If element's popover
attribute is in the auto state, then:
Run hide all popovers until given element, focusPreviousElement, and dontFireBeforetoggle.
If element is not in document's auto popover list:
If throwExceptions is true, then throw an
"InvalidStateError
" DOMException
.
Otherwise, return.
Assert: The last item in document's auto popover list is element.
Remove element from document's auto popover list.
Set element's popover invoker to null.
If dontFireBeforetoggle is false:
Fire an event named beforetoggle
, using BeforeToggleEvent
, with the
cancelable
attribute initialized to false, the currentState
attribute initialized to "open
", and the newState
attribute initialized to "closed
" at element.
If the result of running check popover validity given element and true is false:
If throwExceptions is true, then throw an
"InvalidStateError
" DOMException
.
Otherwise, return.
Check popover validity is called again because firing the beforetoggle
event could have disconnected this element or
changed its popover
attribute.
Set element's popover visibility state to .
Let previouslyFocusedElement be element's previously focused element.
If previouslyFocusedElement is not null, then:
Set element's previously focused element to null.
If focusPreviousElement is true, then run the focusing steps for previouslyFocusedElement; the viewport should not be scrolled by doing this step.
The togglePopover(force)
method steps are:
If this's popover
attribute is in the
no popover state, then throw a
"NotSupportedError
" DOMException
.
If this is not connected, then throw a
"InvalidStateError
" DOMException
.
If this's popover visibility state is showing, and force is not present or false, then run the hide popover algorithm given this, true, false, and true.
Otherwise, if force is not present or true, then run show popover given this and true.
To hide all popovers until, given an HTML element endpoint, a boolean focusPreviousElement, and a boolean dontFireBeforetoggle:
Let document be endpoint's node document.
Let closeAllOpenPopovers be an algorithm which performs the following steps:
Let popover be document's topmost auto popover.
While popover is not null:
Run the hide popover algorithm given popover, focusPreviousElement, dontFireBeforetoggle, and false.
Set popover to document's topmost auto popover.
If endpoint is null, then run closeAllOpenPopovers and return.
Let lastToHide be null.
Let foundEndpoint be false.
For each popover in document's auto popover list:
If popover is endpoint, then set foundEndpoint to true.
Otherwise, if foundEndpoint is true, then set lastToHide to popover and break.
If foundEndpoint is false, then run closeAllOpenPopovers and return.
While lastToHide is not null and lastToHide's popover visibility state is showing and document's auto popover list is not empty:
Run the hide popover algorithm given document's auto popover list's last element, focusPreviousElement, dontFireBeforetoggle, and false.
The hide all popovers until algorithm is used in several cases to hide all popovers that don't stay open when something happens. For example, during light-dismiss of a popover, this algorithm ensures that we close only the popovers that aren't related to the node clicked by the user.
To find the topmost popover ancestor, given a Node
newPopover, perform the following steps. They return an HTML element or null.
The topmost popover ancestor algorithm will return the topmost (highest in the auto popover list) ancestor popover for the provided popover. Popovers can be related to each other in several ways, creating a tree of popovers. There are two paths through which one popover (call it the "child" popover) can have an ancestor popover (call it the "parent" popover):
The popovers are nested within each other in the DOM tree. In this case, the descendant popover is the "child" and its ancestor popover is the "parent".
An invoking element (e.g. a button
) has one of the invoking attributes (e.g.
popovertoggletarget
) pointing to a popover. In
this case, the popover is the "child", and the DOM-contained popover of the invoking element is
the "parent". The invoker must be in a popover and reference an open popover.
In each of the relationships formed above, the parent popover must be strictly lower in the auto popover list than the child popover, or it does not form a valid ancestral relationship. This eliminates non-showing popovers and self-pointers (e.g. a popover with an anchor attribute that points back to the same popover), and it allows for the construction of a well-formed tree from the (possibly cyclic) graph of connections. For example, if two popovers have anchors pointing to each other, the only valid relationship is that the first one to open is the "parent" and the second is the "child". Only auto popovers are considered.
Let popoverPositions be an empty map.
Let index be 0.
Let document be newPopover's node document.
For each popover in document's auto popover list:
Set popoverPositions[popover] to index.
Increment index by 1.
Set popoverPositions[newPopover] to index.
Increment index by 1.
Let topmostPopoverAncestor be null.
Let checkAncestor be an algorithm which performs the following steps given candidate:
If candidate is null, then return.
Let candidateAncestor be the result of running nearest inclusive open popover given candidate.
If candidateAncestor is null, then return.
Let candidatePosition be popoverPositions[candidateAncestor].
If topmostPopoverAncestor is null or popoverPositions[topmostPopoverAncestor] is less than candidatePosition, then set topmostPopoverAncestor to candidateAncestor.
Run checkAncestor given the result of running nearest inclusive open popover given newPopover's parent node within the flat tree.
For each invoker in document's popover invokers:
If invoker's popover target element is newPopover, then run checkAncestor given invoker.
return topmostPopoverAncestor.
To find the nearest inclusive open popover given a Node
node, perform the following steps. They return an HTML
element or null.
Let currentNode be node.
While currentNode is not null:
If currentNode's popover
attribute is in
the auto state and currentNode's
popover visibility state is showing,
then return currentNode.
Set currentNode to currentNode's parent in the flat tree.
Return null.
To find the topmost auto popover given a
Document
document, perform the following steps. They return an HTML element or null.
If document's auto popover list is not empty, then return document's auto popover list's last element.
Return null.
To perform the popover focusing steps for an HTML element subject:
Let control be the focus delegate of subject given
"other
" and true.
If control is null, then return.
Run the focusing steps given control.
Let topDocument be the active document of control's node document's browsing context's top-level browsing context.
If control's node document's origin is not the same as the origin of topDocument, then return.
Empty topDocument's autofocus candidates.
Set topDocument's autofocus processed flag to true.
To check popover validity for an HTML element element given a boolean expectedToBeShowing, perform the following steps. They return a boolean.
If element's popover
attribute is in the
no popover state, then return false.
If element is not connected, then return false.
If expectedToBeShowing is true and element's popover visibility state is not showing, then return false.
If expectedToBeShowing is false and element's popover visibility state is not , then return false.
If element is a dialog
element and has the open
attribute, then return false.
If element's fullscreen flag is set, then return false.
Return true.
Supported elements may have the following content attributes, known as the popover target attributes:
popovertoggletarget
popoverhidetarget
popovershowtarget
The popover target attributes allow certain types of buttons to show and hide
element with the popover
attribute. If a popover target
attribute is specified, then that attribute's value must be the ID of element with the popover
attribute.
The following shows how popovershowtarget
can
be used to open a popover:
<div popover=auto id="foo">
This is a popover!
</div>
<button popovershowtarget="foo">
Show a popover
</button>
The following shows how popovertoggletarget
can open and close a manual popover, which can't be closed with light dismiss:
<div popover=manual id="foo">
This is a popover!
</div>
<button popovertoggletarget="foo">
Show or hide a popover
</button>
The popover target attributes are only supported on the following elements:
button
elements
input
elements in the Submit
Button state.
input
elements in the Image
Button state.
input
elements in the Reset
Button state.
interface mixin PopoverTargetElement {
[CEReactions] attribute Element? popoverToggleTargetElement;
[CEReactions] attribute Element? popoverHideTargetElement;
[CEReactions] attribute Element? popoverShowTargetElement;
};
The popoverToggleTargetElement
IDL attribute must
reflect the popovertoggletarget
attribute.
The popoverHideTargetElement
IDL attribute must
reflect the popoverhidetarget
attribute.
The popoverShowTargetElement
IDL attribute must
reflect the popovershowtarget
attribute.
To run the popover target attribute activation behavior given a Node
node:
Let popover be node's popover target element.
If popover is null, then return.
If node doesn't have the popovertoggletarget
attribute, then:
If node has a popovershowtarget
attribute and popover's
popover visibility state is showing,
then return.
If node has a popoverhidetarget
attribute and popover's
popover visibility state is ,
then return.
If popover's popover visibility state is showing, then run the hide popover algorithm given popover, true, false, and false.
Otherwise:
Set popover's popover invoker to node.
Run show popover given popover and false.
To get the popover target element given a Node
node, perform
the following steps. They return an HTML element or null.
If node is not supported, then return null.
If node is disabled, then return null.
If node has a form owner and node is a submit button, then return null.
Let idref be null.
If node has a popovertoggletarget
attribute, then set
idref to the value of node's popovertoggletarget
attribute.
Otherwise, if node has a popovershowtarget
attribute, then set idref
to the value of node's popovershowtarget
attribute.
Otherwise, if node has a popoverhidetarget
attribute, then set idref
to the value of node's popoverhidetarget
attribute.
If idref is null, then return null.
Let popoverElement be the first element in tree order, within node's root's descendants, whose ID is idref; otherwise, if there is no such element, null.
If popoverElement is null, then return null.
If popoverElement's popover
attribute is in
the no popover state, then return null.
Return popoverElement.
To get the popover invokers given a Document
document:
Return an HTMLCollection
rooted at document whose filter matches
elements which support the popover
target attributes.
"Light dismiss" means that pressing the Esc key or clicking outside of
a popover whose popover
attribute is in the auto state will close the popover.
Canceling popovers: When Document
has a
topmost auto popover showing, user agents may provide a user interface that, upon
activation, queues an element task on the user
interaction task source given topmost auto popover to run the hide
popover algorithm given the topmost auto popover, true, and false.
To light dismiss open popovers, given an Event
event and a
Node
node:
Let topmostPopover be the result of running topmost auto popover given node.
If topmostPopover is null, then return.
Let target be event's target.
Let document be node's node document.
If event is a PointerEvent
and event's type
is pointerdown
,
then:
Set document's popover pointerdown target to the result of
running topmost clicked popover given target and "inclusive
".
If event is a PointerEvent
and event's type
is pointerup
,
then:
Let ancestor be the result of running topmost clicked popover given target.
Let sameTarget be true if ancestor is document's popover pointerdown target.
Set document's popover pointerdown target to null.
If sameTarget is true, then run hide all popovers until given ancestor, false, and false.
Light dismiss open popovers is called by the Pointer Events spec when the user clicks or touches anywhere on the page.
To find the topmost clicked popover, given a Node
node:
Let clickedPopover be the result of running nearest inclusive open popover given node.
Let invokerPopover be the result of running nearest inclusive target popover for invoker given node.
Let getStackPosition be an algorithm which performs the following steps given an HTML element popover:
Let popoverList be popover's node document's auto popover list.
If popover is in popoverList, then return the index of popover in popoverList + 1.
Return 0.
If the result of running getStackPosition given clickedPopover is greater than the result of running getStackPosition given invokerPopover, then return clickedPopover.
Return invokerPopover.
To find the nearest inclusive target popover for invoker given a Node
node:
Let currentNode be node.
While currentNode is not null:
Let targetPopover be currentNode's popover target element.
If targetPopover is not null and targetPopover's popover
attribute is in the auto state and targetPopover's popover
visibility state is showing, then return
targetPopover.
Set currentNode to currentNode's ancestor in the flat tree.
BeforeToggleEvent
interface[Exposed=Window]
interface BeforeToggleEvent : Event {
constructor(DOMString type, optional BeforeToggleEventInit eventInitDict = {});
readonly attribute DOMString currentState;
readonly attribute DOMString newState;
};
dictionary BeforeToggleEventInit : EventInit {
DOMString currentState = "";
DOMString newState = "";
};
event.currentState
Set to "closed
" when transitioning from closed to open, or set to
"open
" when transitioning from open to closed.
event.newState
Set to "open
" when transitioning from closed to open, or set to "closed
" when transitioning from open to closed.
The currentState
attribute must return the
value it was initialized to. It is initialized to "open
" if the element
with the popover
attribute's popover visibility
state is showing, otherwise "closed
".
The newState
attribute must return the value it
was initialized to. It is initialized to "closed
" if the element with the
popover
attribute's popover visibility state is
showing, otherwise "open
".