Building a Popover with only CSS

Following Jesus; Husband; Father; Developer; Gamer; Tinkerer; Writing about code
Search for a command to run...

Following Jesus; Husband; Father; Developer; Gamer; Tinkerer; Writing about code
How could I close the popover without clicking on the <summary> element again? I would like to place a "close" icon in the <p> like in a modal, but can't tell how to hide the popover when the icon is clicked..
You might want to start reaching for a touch of JavaScript. It probably could be done without, but the complexity starts to make the tradeoff not make sense to avoid JS for the sake of avoiding JS. The JavaScript would listen for a click on your close icon and then remove the open attribute from the details DOM element.
Today ChatGPT lied to me, so I’m setting the record straight. This is my question: “If an endpoint in an OpenAPI spec has multiple tags, what will Swagger Codegen do?”. Because Swagger Codegen organized the generated code into api/tag_name_api files....

A Short Story

Universal Libraries, The Internet, and Generative AI

This is the article I wished existed when I needed to support accounting functions. Double-entry Bookkeeping may seem esoteric and unnecessarily complicated, but actually describes a simple framework for maintaining a correctible and auditable record...

How to Change Databases without Downtime

On this page
Popovers were once firmly in the domain of JavaScript. Today let's examine one of our non-JS options to build them.
<details> element for the interactive open/close functionality.Attribute selector [attribute] - selects an element with attribute regardless of value
Child 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
outline - used to change the default behavior of showing an outline when focused on a details elementlist-style - the standard way to control the default arrow displayed beside the summarytext-decoration - to visually denote what elements have a popover availabletransform and position styles - to move the popover into the correct positionStep 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>
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.
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.
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.