Skip to main
Article
A symmetrical knot with thick rope lying on weathered wood.

Anchor Positioning Is Disruptive

New layouts will be possible

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.

A demo from Tab Atkins-Bittner’s slides from CSS Day 2024

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.

A rough wireframe of photos and aligned names

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:

  1. The left side of the names should be 1em to the right of the photos.
  2. Each name should be in the same row as its photo, starting at the top.
  3. 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>.

<ul>
  <li>
    <img src="photo1.jpg" />
    <h2>Name 1</h2>
  </li>
  <li>
    <img src="photo2.jpg" />
    <h2>Name 2</h2>
  </li>
  ...
</ul>

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.

h2 {
  position: absolute;
  left: calc(anchor(--photos right) + 1em);
}

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.

li {
  anchor-name: --photo;
  anchor-scope: --photo;
}
h2 {
  top: anchor(--photo top);
}

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.

h2 {
  anchor-name: --title;
  top: max(anchor(--photo top), anchor(--title bottom, 0));
}

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.

See the Pen CSS Anchor Positioning - Yearbook layout by @jamessw on CodePen.

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!

  1. Sponsor us. We display sponsor logos and avatars here on our website and offer other fun perks.
  2. 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

Open Collective Avatar for benface

Common Loons

Open Collective Avatar for ScheppOpen Collective Avatar for ThijsOpen Collective Avatar for Outline GbROpen Collective Avatar for Mat MarquisOpen Collective Avatar for AnonymousOpen Collective Avatar for Paul van BuurenOpen Collective Avatar for William KillerudOpen Collective Avatar for Nikita DubkoOpen Collective Avatar for JohannesOpen Collective Avatar for Eric PortisOpen Collective Avatar for Nicolas ChevobbeOpen Collective Avatar for Pascal DuezOpen Collective Avatar for Tyson GachOpen Collective Avatar for MayankOpen Collective Avatar for thanks.devOpen Collective Avatar for Syntax

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!

Recent Articles

  1. A pay-to-use pair of binoculars at a scenic overlook.
    Article post type

    Updates to the Most Desired CSS Feature You Can’t Use Yet

    Performance, scope, and fallbacks for the anchor positioning polyfill

    Our sponsors are supporting the continued development of the CSS Anchor Positioning Polyfill. Here’s a summary of the latest updates.

    see all Article posts
  2. A green on dark-gray horizontal bar chart, with the labels cut off
    Article post type

    What do survey demographics tell us?

    Are we measuring what we meant to measure?

    There’s been a lot of interest in the results of the annual State of CSS survey, but are we asking all the right questions?

    see all Article posts
  3. A gallery of numbered images in four columns
    Article post type

    Choosing a Masonry Syntax in CSS

    What makes something a ‘grid’, and what’s at stake?

    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.

    see all Article posts