Anchor Positioning Grows a Tree-Scoped Scope

The CSS Working Group has been busy tightening behavior around anchor positioning, and the latest telecon minutes show a few notable resolutions. The headline decision concerns how anchor-scope matches names, but the group also settled details about scroll-start-target and underline positioning.

The anchor-scope Matching Problem

The anchor-name property registers an element as an anchor, and elements using position-anchor can attach to it. Nothing forces anchor names to be unique, so reusing the same name across components is allowed. In practice, however, this leads to a problem: when multiple anchors share a name, targets all resolve to the last instance in the DOM.

<ul>
   <li>
	<div class="anchor">Anchor 1</div>
	<div class="target">Target 1</div>
   </li>
   <li>
	<div class="anchor">Anchor 2</div>
	<div class="target">Target 2</div>
   </li>
   <li>
	<div class="anchor">Anchor 3</div>
	<div class="target">Target 3</div>
   </li>
</ul>
.anchor {
  anchor-name: --my-anchor;
}

.target {
  position: absolute;
  position-anchor: --my-anchor;
  position-area: top right;
}

The anchor-scope property is the intended fix: it limits an anchor's discoverability to its own subtree. For example:

.anchor {
  anchor-name: --my-anchor;
  anchor-scope: --my-anchor;
}

That solves the immediate issue, but it opens a deeper question: what exactly does "matching" mean when tree scopes are involved? The spec did not clearly state whether the value of anchor-scope is itself tree-scoped. Since both anchor-name and position-anchor are tree-scoped references, the group debated whether anchor-scope should follow suit.

TabAtkins argued that an anchor inside a shadow tree with a part involved creates problems if anchor scopes are not tree-scoped. The group agreed, and the discussion expanded beyond anchor positioning to view transitions, which rely on similar name-matching semantics across tree scopes.

The resulting resolution covers the general principle:

Whenever you are comparing names, and at least one is tree scoped, then both are tree scoped, and the scoping has to be exact (not subtree).

A second, related question was whether the all keyword—which scopes every anchor name—should behave as a tree-scoped value. This too was resolved affirmatively, meaning all only applies within the current tree scope. The group noted this follows the same pattern as view-transition-group.

scroll-start-target: Resolving Multiple Targets

The next topic came from CSS Scroll Snap Module Level 2, which introduces the scroll-start-target property for controlling the initial scroll position. In a carousel, setting scroll-start-target: auto on an element tells the scroll container to start scrolled to that element:

<div class="carousel">
  <img src="img1.jpg">
  <img src="img2.jpg">
  <img src="img3.jpg" class="origin">
  <img src="img4.jpg">
  <img src="img5.jpg">
</div>
.carousel {
  overflow-inline: auto;
}

.carousel .origin {
  scroll-start-target: auto;
}

Today this requires JavaScript:

document.querySelector(".origin").scrollIntoView({
  behavior: "auto",
  block: "center",
  inline: "center"
});

The question centered on what should happen when a scroll container lists multiple elements as scroll-start-targets. The current draft spec says the user agent should pick the one that comes first in tree order. That works fine for one-dimensional scrolling but feels lackluster for containers scrollable in both axes, where an author might want to target one element horizontally and a different one vertically.

After exploring the option of simply choosing the first element in DOM order, the group settled on a more nuanced approach: scroll to each target sequentially in reverse-DOM order, but only scroll as far as needed for the final (first-in-DOM) target to be on screen. Flackr explained that this produces the expected result—the first item in DOM order is the priority—while still revealing the other targets as much as possible.

The resolution:

When scroll-start-target targets multiple elements, scroll to each in reverse DOM order with text to specify priority is the first item.

Language-Aware Underline Placement

Last, the group revisited text-underline-position and its auto initial value. The spec defines auto as placing the underline "at or below the alphabetic baseline," but it does not address vertical writing modes. For languages like Japanese and Mongolian, the underline should appear on the right side of the text, not below it. Chrome and Firefox already implement this behavior for vertical Japanese text under auto.

The WG considered three paths: keep the spec as-is and rely on the UA stylesheet to switch underline position per language; introduce a new auto value to text-emphasis-position that would cover both text-emphasis-position and text-underline-position; or adopt mixed behavior (an auto value for underlines, UA stylesheet overrides for emphasis marks).

Group members voted and resolved:

Add auto value for text-emphasis-position, and change the meaning of text-underline-position: auto to care about left vs. right in vertical text.

These resolutions are not final spec text, but they strongly signal where these features are heading. The full minutes and the resolution list are available on W3C.org for those who want the complete record.