Not quite a year ago, I published an exploration of how I used layered backgrounds to create the appearance of a single bent line that connected one edge of the design to whichever navbar link corresponded to the current page. It was fairly creative, if I do say so myself, but even then I knew  —  and said explicitly!  —  that it was a hack, and that I really wanted to use anchor positioning to do it cleanly.

Now that anchor positioning is supported behind a developer flag in Chrome, we can experiment with it, as I did in the recent post “Nuclear Anchored Sidenotes”. Well, today, I’m back on my anchor BS with a return to that dashed navbar connector as seen on wpewebkit.org, and how it can be done more cleanly and simply, just as I’d hoped last year.

First, let’s look at the thing we’re trying to recreate.

The connecting line, as done with a bunch of forcibly-sized and creatively overlapped background gradient images.To understand the ground on which we stand, let’s make a quick perusal of the simple HTML structure at play here. At least, the relevant parts of it, with some bits elided by ellipses for clarity.

```

`` Inside that (unclassed! on purpose!)

    , there are a number of list items, each of which holds a hyperlink. Whichever list item contains the hyperlink that corresponds to the current page gets a class ofcurrentPage`, because class naming is a deep and mysterious art.

    To that HTML structure, the following bits of CSS trickery were applied in the work I did last year, brought together in this code block for the sake of brevity (note this is the old thing, not the new anchoring hotness):

    nav.global div {display: flex;justify-content: space-between;gap: 1em;max-width: var(--mainColMax);margin: 0 auto;height: 100%;background: var(--dashH);}@media (min-width: 720px) {nav.global ul li.currentPage::before {content: '';position: absolute;z-index: 1;top: 50%;bottom: 0;left: 50%;right: 0;background:var(--dashV),linear-gradient(0deg, #FFFF 2px, transparent 2px);background-size: 1px 0.5em, auto;}nav.global ul li.currentPage {position: relative;}nav.global ul li.currentPage a {position: relative;z-index: 2;padding: 0;padding-block: 0.25em;margin: 1em;background: var(--dashH);background-size: 0.5em 1px;background-position: 50% 100%;background-color: #FFF;color: inherit;}} If you’re wondering what the heck is going on there, please feel free to read the post from last year. You can even go read it now, if you want, even though I’m about to flip most of that apple cart and stomp on the apples to make ground cider. Your life is your own; steer it as best suits you.

    Anyway, here are the bits I’m tearing out to make way for an anchor-positioning solution. The positioning-edge properties (top, etc.) removed from the second rule will return shortly in a more logical form.

    nav.global div {display: flex;justify-content: space-between;gap: 1em;max-width: var(--mainColMax);margin: 0 auto;height: 100%; ~~background: var(--dashH);~~}@media (min-width: 720px) {nav.global ul li.currentPage::before {content: '';position: absolute; ~~z-index: 1;top: 50%;bottom: 0;left: 50%;right: 0;background:var(--dashV),linear-gradient(0deg, #FFFF 2px, transparent 2px);background-size: 1px 0.5em, auto;~~} ~~nav.global ul li.currentPage {position: relative;}~~nav.global ul li.currentPage a { ~~position: relative;z-index: 2;~~padding: 0;padding-block: 0.25em;margin: 1em; ~~background: var(--dashH);background-size: 0.5em 1px;background-position: 50% 100%;background-color: #FFF;~~color: inherit;}} That pulls out not only the positioning edge properties, but also the background dash variables and related properties. And a whole rule to relatively position the currentPage list item, gone. The resulting lack of any connecting line being drawn is perhaps predictable, but here it is anyway.

    The connecting line disappears as all its support structures and party tricks are swept away.With the field cleared of last year’s detritus, let’s get ready to anchor!

    Step one is to add in positioning edges, for which I’ll use logical positioning properties instead of the old physical properties. Along with those, a negative Z index to drop the generated decorator (that is, a decorative component based on generated content, which is what this ::before rule is creating) behind the entire set of links, dashed borders along the block and inline ends of the generated decorator, and a light-red background color so we can see the decorator’s placement more clearly.

    nav.global ul li.currentPage::before {content: '';position: absolute; inset-block-start: 0;inset-block-end: 0;inset-inline-start: 0;inset-block-end: 0;z-index: -1;border: 1px dashed;border-block-width: 0 1px;border-inline-width: 0 1px;background-color: #FCC;} I’ll also give the <a> element inside the currentPage list item a dashed border along its block-end edge, since the design calls for one.

    nav.global ul li.currentPage a {padding: 0;padding-block: 0.25em;margin: 1em;color: inherit; border-block-end: 1px dashed;} And those changes give us the result shown here.

    The generated decorator, decorating the entirety of its containing block.Well, I did set all the positioning edge values to be 0, so it makes sense that the generated decorator fills out the relatively-positioned <div> acting as its containing block. Time to fix that.

    What we need to do give the top and right  —  excuse me, the block-start and inline-end  —  edges of the decorator a positioning anchor. Since the thing we want to connect the decorator’s visible edges to is the <a> inside the currentPage list item, I’ll make it the positioning anchor:

    nav.global ul li.currentPage a {padding: 0;padding-block: 0.25em;margin: 1em;color: inherit;border-block-end: 1px dashed; anchor-name: --currentPageLink;} Yes, you’re reading that correctly: I made an anchor be an anchor.

    (That’s an HTML anchor element being designated as a CSS positioning anchor, to be clear. Sorry to pedantically explain the joke and thus ruin it, but I fear confusion more than banality.)

    Now that we have a positioning anchor, the first thing to do, because it’s more clear to do it in this order, is to pin the inline-end edge of the generated decorator to its anchor. Specifically, to pin it to the center of the anchor, since that’s what the design calls for.

    nav.global ul li.currentPage::before {content: '';position: absolute;inset-block-start: 0;inset-block-end: 0;inset-inline-start: 0;inset-inline-end: anchor(--currentPageLink center);z-index: -1;border: 1px dashed;border-block-width: 0 1px;border-inline-width: 0 1px;background-color: #FCC;} Because this anchor() function is being used with an inline inset property, the center here refers to the inline center of the referenced anchor (in both the HTML and CSS senses of that word) --currentPageLink, which in this particular case is its horizontal center. That gives us the following.

    The generated decorator with its inline-end edge aligned with the inline center of the anchoring anchor.The next step is to pin the top block edge of the generated decorator with respect to its positioning anchor. Since we want the line to come up and touch the block-end edge of the anchor, the end keyword is used to pin to the block end of the anchor (in this situation, its bottom edge).

    nav.global ul li.currentPage::before {content: '';position: absolute;inset-block-start: anchor(--currentPageLink end);inset-block-end: 0;inset-inline-start: 0;inset-inline-end: anchor(--currentPageLink center);z-index: -1;border: 1px dashed;border-block-width: 0 1px;border-inline-width: 0 1px;background-color: #FCC;} Since the inset property in this case is block-related, the end keyword here means the block end of the anchor (again, in both senses). And thus, the job is done, except for removing the light-red diagnostic background.

    The generated decorator with its block-start edge aligned with the block-end edge of the anchoring anchor.Once that red background is taken out, we end up with the following rules inside the media query:

    nav.global ul li.currentPage::before {content: '';position: absolute;inset-block-start: anchor(--currentPageLink bottom);inset-block-end: 0;inset-inline-start: 0;inset-inline-end: anchor(--currentPageLink center);z-index: -1;border: 1px dashed;border-block-width: 0 1px;border-inline-width: 0 1px;}nav.global ul li.currentPage a {padding: 0;padding-block: 0.25em;margin: 1em;color: inherit;border-block-end: 1px dashed;anchor-name: --currentPageLink;} The inline-start and block-end edges of the generated decorator still have position values of 0, so they stick to the edges of the containing block (the <div>). The block-start and inline-end edges have values that are set with respect to their anchor. That’s it, done and dusted.

    The connecting line is restored, but is now a lot easier to manage from the CSS side.…okay, okay, there are a couple more things to talk about before we go.

    First, the dashed borders I used here don’t look fully consistent with the other dashed “borders” in the design. I used actual borders for the CSS in this article because they’re fairly simple, as CSS goes, allowing me to focus on the topic at hand. To make these borders fully consistent with the rest of the design, I have two choices:

    1. Remove the borders from the generated decorator and put the background-trick “borders” back into it. This would be relatively straightforward to do, at the cost of inflating the rules a little bit with background sizing and positioning and all that.
    2. Convert all the other background-trick “borders” to be actual dashed borders. This would also be pretty straightforward, and would reduce the overall complexity of the CSS.

    On balance, I’d probably go with the first option, because dashed borders still aren’t fully visually consistent from browser to browser, and people get cranky about those kinds of inconsistencies. Background gradient tricks give you more control in exchange for you writing more declarations. Still, either choice is completely defensible.

    Second, you might be wondering if that <div> was even necessary. Not technically, no. At first, I kept using it because it was already there, and removing it seemed like it would require refactoring a bunch of other code not directly related to this post. So I didn’t.

    But it tasked me. It tasked me. So I decided to take it out after all, and see what I’d have to do to make it work. Once I realized doing this illuminated an important restriction on what you can do with anchor positioning, I decided to explore it here.

    As a reminder, here’s the HTML as it stood before I started removing bits:

    ```

    `` Originally, the

    was put there to provide a layout container for the logo and navbar links, so they’d be laid out to line up with the right and left sides of the page content. The