Only Chris, right? You’ll want to view this in a Chromium browser:
This is exactly the sort of thing I love, not for its practicality (cuz it ain’t), but for how it illustrates a concept. Generally, tutorials and demos try to follow the “rules” — whatever those may be — yet breaking them helps you understand how a certain thing works. This is one of those.
The concept is pretty straightforward: one target element can be attached to multiple anchors on the page.
We’ve gotta register the anchors and attach the .target
to them:
.anchor-1 {
anchor-name: --anchor-1;
}
.anchor-2 {
anchor-name: --anchor-2;
}
.target {
}
Wait, wait! I didn’t attach the .target
to the anchors. That’s because we have two ways to do it. One is using the position-anchor
property.
.target {
position-anchor: --anchor-1;
}
That establishes a target-anchor relationship between the two elements. But it only accepts a single anchor value. Hmm. We need more than that. That’s what the anchor()
function can do. Well, it doesn’t take multiple values, but we can declare it multiple times on different inset properties, each referencing a different anchor.
.target {
top: anchor(--anchor-1, bottom);
}
The second piece of anchor()
‘s function is the anchor edge we’re positioned to and it’s gotta be some sort of physical or logical inset — top
, bottom
, start
, end
, inside
, outside
, etc. — or percentage. We’re bascially saying, “Take that .target
and slap it’s top
edge against --anchor-1
‘s bottom edge.
That also works for other inset properties:
.target {
top: anchor(--anchor-1 bottom);
left: anchor(--anchor-1 right);
bottom: anchor(--anchor-2 top);
right: anchor(--anchor-2 left);
}
Notice how both anchors are declared on different properties by way of anchor()
. That’s rad. But we aren’t actually anchored yet because the .target
is just like any other element that participates in the normal document flow. We have to yank it out with absolute positioning for the inset properties to take hold.
.target {
position: absolute;
top: anchor(--anchor-1 bottom);
left: anchor(--anchor-1 right);
bottom: anchor(--anchor-2 top);
right: anchor(--anchor-2 left);
}
In his demo, Chris cleverly attaches the .target
to two elements. What makes it clever is that
allows you to click and drag it to change its dimensions. The two of them are absolutely positioned, one pinned to the viewport’s top-left edge and one pinned to the bottom-right.
If we attach the .target's top
and left
edges to --anchor-1
‘s bottom
and right
edges, then attach the target's bottom
and right
edges to --anchor-2
‘s top
and left
edges, we’re effectively anchored to the two elements. This is what allows the
.target
element to stretch with the elements when they are resized.
But there’s a small catch: a is resized from its bottom-right corner. The second
is positioned in a way where the resizer isn’t directly attached to the
.target
. If we rotate(180deg)
, though, it’s all good.
Again, you’ll want to view that in a Chromium browser at the time I’m writing this. Here’s a clip instead if you prefer.
That’s just a background-color
on the .target
element. We can put a little character in there instead as a background-image
like Chris did to polish this off.
Fun, right?! It still blows my mind this is all happening in CSS. It wasn’t many days ago that something like this would’ve been a job for JavaScript.