I do know, tremendous area of interest, but it surely might be any loop, actually. The problem is having a number of tooltips on the identical web page that make use of the Popover API for toggling goodness and CSS Anchor Positioning for attaching a tooltip to its respective anchor aspect.
There’s loads of transferring items when working with popovers:
- A
popover
wants an ID (and an accessible position whereas we’re at it). - A
popovertarget
must reference that ID. - IDs must be distinctive for semantics, sure, but in addition to hook a
popover
right into apopovertarget
.
That’s simply the half coping with the Popover API. Turning to anchors:
- An anchor wants an
anchor-name
. - A goal aspect must reference that
anchor-name
. - Every
anchor-name
should be distinctive to connect the goal to its anchor correctly.
The necessities themselves are difficult. But it surely’s tougher working inside a loop since you want a method to generate distinctive IDs and anchor names so every part is attached correctly with out conflicting with different parts on the web page. In WordPress, we question an array of web page objects:
$property_query = new WP_Query(array(
'post_type' => 'web page',
'post_status' => 'publish',
'posts_per_page' => -1, // Question all of them!
'orderby' => 'title',
'order' => "ASC"
));
Earlier than we get into our whereas()
assertion I’d prefer to stub out the HTML. That is how I desire a web page object to look inside its container:
<div class="almanac-group">
<div class="group-letter"><a href="#">A</a></div>
<div class="group-list">
<particulars id="" class="group-item">
<abstract>
<h2><code>accent-color</code></h2>
</abstract>
</particulars>
<!-- Repeat for all properties -->
</div>
</div>
<!-- Repeat for the whole alphabet -->
OK, let’s stub out the tooltip markup whereas we’re right here, focusing simply contained in the <particulars>
aspect since that’s what represents a single web page.
<particulars id="web page" class="group-item">
<abstract>
<h2><code>accent-color</code></h2>
<span id="tooltip" class="tooltip">
<!-- Popover Goal and Anchor -->
<button class="info-tip-button" aria-labelledby="experimental-label" popovertarget="experimental-label">
<!-- and many others. -->
</button>
<!-- Popover and Anchor Goal -->
<div popover id="experimental-label" class="info-tip-content" position="tooltip">
Experimental function
</div>
</span>
</abstract>
</particulars>
With me to this point? We’ll begin with the Popover aspect of issues. Proper now we’ve a <button>
that’s related to a <div popover>
. Clicking the previous toggles the latter.
Styling isn’t actually what we’re speaking about, but it surely does assist to reset a number of popover issues so it doesn’t get that border and sit instantly within the heart of the web page. You’ll wish to take a look at Michelle Barker’s article for some nice ideas that make this improve progressively.
.info-tip {
place: relative; /* Units containment */
/* Bail if Anchor Positioning is just not supported */
[popovertarget] {
show: none;
}
/* Fashion issues up if Anchor Positioning is supported */
@helps (anchor-name: --infotip) {
[popovertarget] {
show: inline;
place: relative;
}
[popover] {
border: 0; /* Removes default border */
margin: 0; /* Resets placement */
place: absolute; /* Required */
}
}
That is additionally the purpose at which you’ll wish to begin utilizing Chrome as a result of Safari and Firefox are nonetheless engaged on supporting the function.
We’re doing good! The massive deal in the intervening time is positioning the tooltip’s content material in order that it’s beside the button. That is the place we are able to begin working with Anchor Positioning. Juan Diego’s information is the bee’s knees should you’re on the lookout for a deep dive. The gist is that we are able to join an anchor to its goal aspect in CSS. First, we register the <button>
because the anchor aspect by giving it an anchor-name
. Then we anchor the <div popover>
to the <button>
with position-anchor
and use the anchor()
perform on its inset properties to place it precisely the place we would like, relative to the <button>
:
.tooltip {
place: relative; /* Units containment */
/* Bail if Anchor Positioning is just not supported */
[popovertarget] {
show: none;
}
/* Fashion issues up if Anchor Positioning is supported */
@helps (anchor-name: --tooltip) {
[popovertarget] {
anchor-name: --tooltip;
show: inline;
place: relative;
}
[popover] {
border: 0; /* Removes default border */
margin: 0; /* Resets placement */
place: absolute; /* Required */
position-anchor: --tooltip;
high: anchor(--tooltip -15%);
left: anchor(--tooltip 110%);
}
}
}
That is precisely what we would like! But it surely’s additionally the place issues extra sophisticated once we attempt to add extra tooltips to the web page. Discover that each buttons wish to cull the identical tooltip.
That’s no good. What we want is a singular ID for every tooltip. I’ll simplify the HTML so we’re wanting on the proper spot:
<particulars>
<!-- ... -->
<!-- Popover Goal and Anchor -->
<button class="info-tip-button" aria-labelledby="experimental-label" popovertarget="experimental-label">
<!-- ... -->
</button>
<!-- Popover and Anchor Goal -->
<div popover id="experimental-label" class="info-tip-content" position="tooltip">
Experimental function
</div>
<!-- ... -->
</particulars>
The popover has an ID of #experimental-label
. The anchor references it within the popovertarget
attribute. This connects them but in addition connects different tooltips which can be on the web page. What can be supreme is to have a sequence of IDs, like:
<!-- Popover and Anchor Goal -->
<div popover id="experimental-label-1" class="info-tip-content" position="tooltip"> ... </div>
<div popover id="experimental-label-2" class="info-tip-content" position="tooltip"> ... </div>
<div popover id="experimental-label-3" class="info-tip-content" position="tooltip"> ... </div>
<!-- and so forth... -->
We are able to make the web page question right into a perform that we name:
perform letterOutput($letter, $propertyID) {
$property_query = new WP_Query(array(
'post_type' => 'web page',
'post_status' => 'publish',
'posts_per_page' => -1, // Question all of them!
'orderby' => 'title',
'order' => "ASC"
));
}
And when calling the perform, we’ll take two arguments which can be particular solely to what I used to be engaged on. In case you’re curious, we’ve a structured set of pages that go Almanac → Sort → Letter → Characteristic (e.g., Almanac → Properties → A → accent-color
). This perform outputs the kid pages of a “Letter” (i.e., A → accent-color
, anchor-name
, and many others.). A baby web page is likely to be an “experimental” CSS function and we’re marking that within the UI with tooltops subsequent to every experimental function.
We’ll put the HTML into an object that we are able to return when calling the perform. I’ll minimize it down for brevity…
$html .= '<particulars id="web page" class="group-item">';
$html .= '<abstract>';
$html .= '<h2><code>accent-color</code></h2>';
$html .= '<span id="tooltip" class="tooltip">';
$html .= '<button class="info-tip-button" aria-labelledby="experimental-label" popovertarget="experimental-label"> ';
// ...
$html .= '</button>';
$html .= '<div popover id="experimental-label" class="info-tip-content" position="tooltip">';
// ...
$html .= '</div>';
$html .= '</span>';
$html .= '</abstract>';
$html .= '</particulars>';
return $html;
WordPress has some features we are able to leverage for looping via this markup. For instance, we are able to insert the_title()
instead of the hardcoded put up title:
$html .= '<h2><code>' . get_the_title(); . '</code></h2>';
We are able to additionally use get_the_id()
to insert the distinctive identifier related to the put up. For instance, we are able to use it to offer every <particulars>
aspect a singular ID:
$html .= '<particulars id="page-' . get_the_id(); . '" class="group-item">';
That is the key sauce for getting the distinctive identifiers wanted for the popovers:
// Outputs one thing like `id="experimental-label-12345"`
$html .= '<div popover id="experimental-label-' . get_the_id(); . '" class="info-tip-content" position="tooltip">';
We are able to do the very same factor on the <button>
so that every button is wired to the best popover:
$html .= '<button class="info-tip-button" aria-labelledby="experimental-label-' . get_the_id(); . '" popovertarget="experimental-label"> ';
We must do the identical factor to the .tooltip
aspect itself to tell apart one from one other:
$html .= '<span id="tooltip-' . get_the_id(); . '" class="tooltip">';
I can’t precisely recreate a WordPress occasion in a CodePen demo, however right here’s a simplified instance with related markup:
The popovers work! Clicking both one triggers its respective popover
aspect. The issue you might have realized is that the targets are each hooked up to the identical anchor aspect — so it appears like we’re triggering the identical popover
when clicking both button!
That is the CSS aspect of issues. What we want is an analogous method to apply distinctive identifiers to every anchor, however as dashed-idents as an alternative of IDs. One thing like this:
/* First tooltip */
#info-tip-1 {
[popovertarget] {
anchor-name: --infotip-1;
}
[popover] {
position-anchor: --infotip-1;
high: anchor(--infotip-1 -15%);
left: anchor(--infotip-1 100%);
}
}
/* Second tooltip */
#info-tip-2 {
[popovertarget] {
anchor-name: --infotip-1;
}
[popover] {
position-anchor: --infotip-1;
high: anchor(--infotip-1 -15%);
left: anchor(--infotip-1 100%);
}
}
/* Remainder of tooltips... */
That is the place I really feel like I needed to make a compromise. I may have leveraged an @for
loop in Sass to generate distinctive identifiers however then I’d be introducing a brand new dependency. I may additionally drop a <model>
tag instantly into the WordPress template and use the identical features to generate the identical put up identifiers however then I’m sustaining types in PHP.
I selected the latter. I like having dashed-idents that match the IDs set on the .tooltip
and popover
. It ain’t fairly, but it surely works:
$html .= '
<model>
#info-tip-' . get_the_id() . ' {
[popovertarget] {
anchor-name: --infotip-' . get_the_id() . ';
}
[popover] {
position-anchor: --infotip-' . get_the_id() . ';
high: anchor(--infotip-' . get_the_id() . ' -15%);
left: anchor(--infotip-' . get_the_id() . ' 100%);
}
}
</model>'
We’re technically achieved!
The one factor I had left to do for my particular use case was add a conditional assertion that outputs the tooltip solely whether it is marked an “Experimental Characteristic” within the CMS. However you get the thought.
Isn’t there a greater approach?!
Sure! However not fairly but. Bramus proposed a brand new ident()
perform that, when it turns into official, will generate a collection of dashed idents that can be utilized to call issues just like the anchors I’m working with and forestall these names from colliding with each other.
<div class="group-list">
<particulars id="item-1" class="group-item">...</particulars>
<particulars id="item-2" class="group-item">...</particulars>
<particulars id="item-3" class="group-item">...</particulars>
<particulars id="item-4" class="group-item">...</particulars>
<particulars id="item-5" class="group-item">...</particulars>
<!-- and many others. -->
</div>
/* Hypothetical instance — doesn't work! */
.group-item {
anchor-name: ident("--infotip-" attr(id) "-anchor");
/* --infotip-item-1-anchor, --infotip-item-2-anchor, and many others. */
}
Let’s preserve our fingers crossed for that to hit the specs quickly!
Working With A number of CSS Anchors and Popovers Contained in the WordPress Loop initially printed on CSS-Methods, which is a part of the DigitalOcean household. You need to get the publication.
Subscribe to MarketingSolution.
Receive web development discounts & web design tutorials.
Now! Lets GROW Together!