DigitalOcean provides cloud products for every stage of your journey. Get started with $200 in free credit!
The position-anchor
property links an absolutely positioned element to an “anchor” element. This will define the default anchor and is used for the several anchor properties and functions on the “target” element.
In other words, the property positions (or anchors) an element to another element that we set as the property’s value
.target {
position-anchor: --my-anchor
}
By itself, this example does not do anything other than tell the .target
element that it’s positioned (or anchored) to some other element that is represented by a dashed ident called --my-anchor
. The problem is that we haven’t actually defined what --my-anchor
actually is.
We’ll get to a fully working example after we get some more context about the property, including its syntax and accepted values.
Syntax
position-anchor: auto | <anchor-element>;
- Initial value: implicit
- Applies to: Absolutely positioned elements
- Inherited: No
- Percentages: N/A
- Computed value: As specified
- Canonical order: Per grammar
- Animation: Discrete
Values
/* Keyword values */
position-anchor: auto;
/* <dashed-ident> examples */
position-anchor: --anchor;
position-anchor: --my-anchor;
position-anchor: --myAnchor;
/* Global values */
position-anchor: inherit;
position-anchor: initial;
position-anchor: revert;
position-anchor: revert-layer;
position-anchor: unset;
auto
: Links a target element to its implicit anchor. An implicit anchor can be found using the non-standardanchor
global attribute or using the Popover API.<dashed-ident>
: The name of the desired anchor element. The value is called a “dashed” ident because it must be prefixed with two dashes (–) exactly like we do for CSS custom properties, e.g. –my-anchor.
Basic usage
In the first example, using position-anchor
alone won’t have any effect. We’ve told our .target
element that it is anchored to some other element we’re calling --my-anchor
. But what element is --my-anchor
representing? We need that, or else we’re not anchored to anything that actually exists.
The easiest way to define an element as an “anchor” for other elements is to slap the anchor-name
property on the element we want to be the anchor.
Say we have two unrelated elements in HTML:
<div class="anchor">My Anchor</div>
<div class="target">My Target</div>
We want the .anchor
element to be the anchor, and then position the .target
element’s position based on the .anchor
element’s position.
.anchor {
anchor-name: --my-anchor;
}
.target {
position: absolute; /* or position: fixed; */
position-anchor: --my-anchor;
}
That’s it! There is now an association between the .anchor
and .target
elements. When we change the .target
element’s position, it will use the .anchor
element’s position as its starting basis.
But again, we don’t see much happening in this example. That’s because we haven’t changed the .target
element’s position to see that relationship in action. So, let’s turn our attention to two different approaches for updating that element’s position: using the anchor()
function along inset properties or using the inset-area
property.
anchor()
function and inset properties
Method 1: The .target
element being absolutely positioned means it can be moved around using inset properties (top
, right
, bottom
, left
). It would be ideal to position our .target
next to the .anchor
, but how can we know where the .anchor
is to take advantage of inset properties? The anchor
function does exactly that. It takes one side of the anchor and resolves to the <length>
of where it is positioned.
Now we can attach one side of the .target
to another side of the .anchor
.
.target {
position: absolute;
position-anchor: --my-anchor;
top: anchor(bottom);
}
This is basically saying, “Stitch the .target
top side to the .anchor
element’s bottom
edge.” Pictures are worth a thousand words:
The anchor()
function takes the default anchor
linked to the target
element, but we can also directly reference an anchor-name
if we’re being more explicit about what we’re anchoring to.
.target {
position: absolute;
top: anchor(--my-anchor bottom);
}
…or even reference other anchors that are on the page! For example, we can tell the .target
element to anchor itself to the --my-anchor
element, but we can still position it based on the position of any other anchor on the page simply by calling that in the anchor()
function:
.target {
position: absolute;
position-anchor: --my-anchor;
top: anchor(--my-other-anchor bottom);
}
inset-area
property
Method 2: Perhaps an “easier” way to re-position an anchor is using the inset-area
property. You can think of an imaginary 3×3 grid surrounding the .anchor
element:
We then position the .target
element it is anchored to on the grid by column and row, using:
- physical values like
left
,right
,top
andbottom
, - logical values that respect the current writing mode, like
start
andend
), and - the
center
shared value.
For example, if we were to span the .target
element across two tiles on our imaginary grid, we can use the span-
prefix on any value, or even span the .target
element across the entire grid using the span-all
value.
.target {
position: absolute;
position-anchor: --my-anchor;
inset-area: start center,
/* or */
inset-area: bottom left,
/* or */
inset-area: span-top right,
}
Demo
Specification
The position-anchor
property is defined in the CSS Anchor Positioning Module Level 1 specification, which is currently in Working Draft status at the time of writing. That means a lot can change between now and when the feature becomes a formal Candidate Recommendation for implementation, so be careful about using the property on a live website until the specification is adopted by the W3C and implemented by browsers.
Browser support
Dealing with legacy browser support
Anchor positioning is a relatively new CSS module that doesn’t have full browser support and may have issues with older versions. Its most common use case will be for better tooltips, so a polyfill for a simple tooltip element can be found below. It checks if anchor positioning is supported and creates an old-school tooltip below our anchor element.
@supports not (position-anchor: --my-anchor) {
.target {
display: none;
}
.anchor {
position: relative;
display: flex;
justify-content: center;
}
.anchor::before {
content: "My Target";
position: absolute;
top: 100%;
}
}
More information and tutorials
- “CSS Anchor Positioning” (CSSWG specification)
- CSS Anchor Positioning in Practice (YouTube) (Miriam Suzanne and James Stuckey Weber)
- CSS Anchor Positioning in Practice (Notes) (Geoff Graham)
- “Introducing the CSS anchor positioning API” (Una Kravets)
- Anchor Positioning CodePen Collection (James Stuckey Weber)
- “CSS Stuff I’m Excited After the Last CSSWG Meeting” (Juan Diego Rodríguez)
Related
anchor-name
.anchor { anchor-name: --my-anchor; }
left
position
.header { position: fixed; }
inset-block
.element { inset-block: 50px 15%; }
inset-block-end
.element { inset-block-start: 50px; }
inset-block-start
.element {inset-block-start: 1.5rem; }
inset-inline
inset-inline-end
inset-inline-start