The more I play with it, the more convinced I am that anchor positioning is
going to unlock some surprising new layouts.
Many of the initial examples and use cases for anchor positioning are
simplifying existing possibilities, and – don’t misunderstand me – anchor
positioning will simplify how dropdown menus are implemented significantly.
But that’s just the start.
I first got a glimpse at the possibilities while watching the Anchor
Positioning session at CSS Day
2024 from Tab Atkins-Bittner, an editor of the CSS
spec. Hidden in Tab’s
presentation on anchor positioning was the concept of using an
anchored item as an anchor to ensure that anchored elements don’t overlap.
It’s a simple but powerful trick – in the demo, they are building side notes,
with words in a paragraph of text that are anchors for some additional content
displayed inline to the side. top: max(anchor(--word top), anchor(--note bottom)) will set the top of the note to the higher value of the top of the
anchoring word OR the bottom of the note above it.
This concept unlocks a lot of possibilities that I don’t think were easy to
achieve before.
Imagine a high school yearbook’s photo spread. There are rows of headshots, and
to the side of each row, there is a column with the names of each person in that
row. It’s not a terribly difficult layout for print, but there are a few
challenges to implement it in HTML.
First, it would be a challenge to have the name and the photo of each person
together in the HTML. Also, if it needed to be responsive, with different
numbers of photos per row, I’d likely have to have multiple layouts defined in
CSS, and potentially duplicate the items in the HTML, and conditionally show
them based on some magic number.
When working with anchor positioning, I’ve found it helpful to borrow the
concept of constraints from mobile development, where you describe your layout
in terms of relationships between elements. So, let’s start by defining our
constraints:
The left side of the names should be 1em to the right of the photos.
Each name should be in the same row as its photo, starting at the top.
Each name should be below the name preceding it.
This is all possible with anchor positioning, and we can even have the image and
name inside of the same <li>.
We’ll make the <ul> the main photo area, use flex-wrap: wrap to fit as many
photos in a row as possible, and make it an anchor by giving it anchor-name: --photos.
Then we can place the <h2> titles to meet the first constraint.
That’s right – we don’t need to first figure out how many pixels from the left
viewport edge the photos are, we can just declaratively describe what we want.
“Place the left edge at the sum of photos’ right side and 1em”.
We can then satisfy the second constraint, that each name should be in the same
row as its photo.
The top rule simply aligns the top of the name with the top of the photo. The
anchor-scope is important here. By default, if there are multiple elements
that have the same anchor-name, the last element in the DOM will be selected.
Setting anchor-scope on a parent element means that the anchored element won’t
look outside of the parent element for an anchor. This means the <h2> will be
aligned with the top of its photo.
But wait – we have one more constraint. At this point, all the names in a row are
layered on top of each other. We want them to vertically stack instead.
Now, the top of the name will be either the top of the photo OR the bottom of
the title above it, whichever is greater (or further down the page). That’s
because the anchoring element has to come before the anchored element, which
means the reference to anchor(--title) will be the name above it.
I’d recommend viewing this on Codepen
so you can resize the demo. I’ve added a short transition to the top property
so you can see how the names adjust as the names above them move.
Note that Chromium released support for anchor-scope in version 131, but since
the polyfill doesn’t support partial polyfilling, this demo will only work in
Chromium before 125, after 131, or in a non-Chromium browser.
As an added bonus, because the photo and name are in the same <li>, we can add
hover effects so that if one is hovered, both parts are hovered. If the item is
a link they can be inside the same <a>.
What new possibilities for anchor positioning are you excited about? Let us know
by sending us a message on Mastodon or
BlueSky.
And if you’re excited to use anchor positioning before it becomes baseline,
check out our polyfill. It
supports enough of the anchor positioning spec to do most things.
There are two ways to help us keep this work sustainable and centered on your
needs as a developer!
Hire us to develop the Anchor Positioning polyfill or another
OSS language/tool you rely on. Our client work also helps fund our open
source work like this polyfill, so get in touch with us if you have any web
development needs.
Open Source Sponsors
Current Sponsors
A huge thank you to the individuals and organizations
sponsoring OddBird’s open source work!
Blue-Footed Boobies
Common Loons
Sponsor OddBird’s OSS Work
We love contributing back to the languages & tools
that developers rely on,
from CSS& Sass to browser polyfills and Python.
Help us keep that work sustainable
and focused on developer needs!
What makes something a ‘grid’, and what’s at stake?
byMiriam Suzanneon
Back in 2020, Firefox released a prototype for doing ‘masonry’ layout in CSS. Now all the browsers are eager to ship something, but there’s a hot debate about the best syntax to use.