Popovers were once firmly in the domain of JavaScript. Today let's examine one of our non-JS options to build them.
The goals
- Build a popover (click to open/close)
- Limit DOM use
- Require 0 JavaScript
The results
The strategy
- Use the
<details>
element for the interactive open/close functionality. - Style the content to appear in a "popover" box instead of the default inline.
How to get there
The CSS selectors used
Attribute selector
[attribute]
- selects an element withattribute
regardless of valueChild combinator
>
- combines two selectors; narrowing the selection on the right-hand side to only those elements that are direct descendants of elements selected by the left-hand side.Adjacent sibling combinator
+
- combines two selectors; narrowing the selection on the right-hand side to only those elements that are the immediate, subsequent sibling of elements selected by the left-hand side.Universal selector
*
- selects any element:focus
Psuedo-class - Selects an element that currently has "focus" (e.g. last clicked on or tabbed to etc.)::-webkit-details-marker
Psuedo-element - the way to select the default arrow displayed for the summary in Chrome(ish) browsers
Important CSS styles used
-
outline
- used to change the default behavior of showing an outline when focused on adetails
element -
list-style
- the standard way to control the default arrow displayed beside the summary -
text-decoration
- to visually denote what elements have a popover available -
transform
andposition
styles - to move the popover into the correct position
Starting out: the HTML
Step one of our strategy: use the <details>
tag. We'll put the standard <summary>
as the text leading to the popover and we'll place a single <div>
as a sibling to the <summary>
so that we can easily position the content of the popover as one block.
The only special thing we'll add is a data-popover
attribute that holds the particular direction we want the popover to appear in.
<details data-popover="up">
<summary>I'm a popover</summary>
<div>
<h1>Popovers can have lots of content!</h1>
<p>Like paragraphs</p>
<a href="#">and links</a>
</div>
</details>
Styling: get the popover popping
First let's remove the default detail styling the same way we started when we made an accordian in CSS:
details[data-popover] > summary:focus {
outline: none;
}
details[data-popover] > summary::-webkit-details-marker {
display: none;
}
details[data-popover] > summary {
list-style: none;
}
Since we've removed any indication that this is clickable to reveal more content, let's add back a visual indicator (a dotted underline seems to be a common pattern).
details[data-popover] > summary {
list-style: none;
text-decoration: underline dotted teal;
}
Next, let's use position
to make the popover content pop out of the normal rendering flow:
details[data-popover] {
position: relative;
}
details[data-popover] > summary + * {
position: absolute;
}
Note: to make the popover play nicely in paragraphs, as my example shows, add a display: inline
or display: inline-block
to the details[data-popover]
selection.
Styling: popping into the right position
Positioning will actually be exactly the same as when we positioned our CSS tooltips. I won't totally rehash how this works, but work through one example.
details[data-popover="up"] > summary + * {
bottom: calc(0.5rem + 100%);
right: 50%;
transform: translateX(50%);
}
Our popover has already been position: absolute
'ed, so we can now use bottom
, top
, right
, left
and transform
to manipulate the position of our element.
The bottom
and right
styles combine to essentially say: place my bottom 100% of my parent's height plus 0.5rem
away from my parent's bottom and place my right 50% of my parent's width from my parent's right.
Then the transform: translateX
says: from that position, move me 50% of my width to the right.
Combined it becomes a roundabout way of saying: place my center aligned with my parent's center and place me completely above my parent with a little extra space between us.
Wrapping up and side notes
Thanks for reading! I hope I prompted a little thought on what these building blocks can achieve while building on techniques used from previous "With Only CSS" articles.
The popover could also be done as a hover effect (using :hover
). Instead of <details>
, most likely <div>
or <span>
would be used, though the DOM would take the same general structure. And the popover should be shown if both the "summary" or the content is being shown (to allow user interaction with the popover).
I like sharing and finding things like this where common web design patterns can be done without a massive JavaScript library or framework bogging the page down.
If you like them too, follow me! I plan to release more posts in this series.
Top comments (6)
can you please do the example for :hover ? thanks for the anticipate assistance
If you've read my earlier post on building a tooltip you'll see some mechanics of
:hover
. It's a fairly straight forward mixture of this posts HTML with that posts styling.Building a tooltip with only CSS
Nathan Kallman ・ Jun 3 '20 ・ 7 min read
This was very helpful, thank you!
I'm glad it helped you!
This was of great help! Thanks!
You're welcome!