For the past two months, all my livelihood has gone towards reading, researching, understanding, writing, and editing about Anchor Positioning, and with many Almanac entries published and a full Guide guide on the way, I thought I was ready to tie a bow on it all and call it done. I know that Anchor Positioning is still new and settling in. The speed at which itās moved, though, is amazing. And thereās more and more coming from the CSSWG!
That all said, I was perusing the last CSSWG minutes telecon and knew I was in for more Anchor Positioning when I came to the following resolution:
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) (Issue #10526: When does
anchor-scope
āmatchā a name?)
Resolutions arenāt part of the specification or anything, but the strongest of indications about where theyāre headed. So, I thought this was a good opportunity not only to take a peek at what we might get in anchor-scope
and touch on other interesting bits from the telecon.
Remember that you can subscribe and read the full minutes on W3C.org. š
Whatās anchor-scope
?
To register an anchor, we can give it a distinctive anchor-name
and then absolutely positioned elements with a matching position-anchor
are attached to it. Even though it may look like it, anchor-name
doesnāt have to be unique ā we may reuse an anchor element inside a component with the same anchor-name
.
<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>
However, if we try to connect them with CSS,
.anchor {
anchor-name: --my-anchor;
}
.target {
position: absolute;
position-anchor: --my-anchor;
position-area: top right;
}
We get an unpleasant surprise where instead of each .anchor
have their .target
positioned at its top-right edge, meaning they all pile up on the last .anchor
instance. We can see it better by rotating each target a little. Youāll want to check out the next demo in Chrome 125+ to see the behavior:
The anchor-scope
property should make an anchor element only discoverable by targets in their individual subtree. So, the prior example would be fixed in the future like this:
.anchor {
anchor-name: --my-anchor;
anchor-scope: --my-anchor;
}
This is fairly straightforward ā anchor-scope
makes the anchor element available only in that specific subtree. But then we have to ask another question: What should the anchor-scope
own scope be? We canāt have an anchor-scope-scope
property and then an anchor-scope-scope-scope
and so onā¦ so which behavior should it be?
This is what started the conversation, initially from a GitHub issue:
When an
anchor-scope
is specified with a<dashed-ident>
, it scopes the name to that subtree when the anchor name is āmatchingā. The problem is that this matching can be interpreted in at least three ways: (Assuming thatanchor-scope
is a tree-scoped reference, which is also not clear in the spec):
- It matches by the ident part of the name only, ignoring any tree-scope that would be associated with the name, or
- It matches by exact match of the ident part and the associated tree-scope, or
- It matches by some mechanism similar to dereferencing of tree-scoped references, where itās a match when the tree-scope of the anchor-scope-name is an inclusive ancestor of the tree-scope of the anchor query.
And then onto the CSSWG Minutes:
TabAtkins: In anchor positioning, anchor names and references are tree scoped. The
anchor-scope
property that scopes, does not say whether the names are tree scoped or not. Question to decide: should they be?TabAtkins: I think the answer should be yes. If you have an anchor in a shadow tree with a part involved, then problems result if anchor scopes are not tree scoped. This is bad, so I think it should be tree scoped sounds pretty reasonable makes sense to me as far as I can understand it š
This solution of the scope of scoping properties expanded towards View Transitions, which also rely on tree scoping to work:
khush: Thinking about this in the context of view transitions: in that API you give names and the tree scope has to be the same for them to match. There is another view transitions feature where Iām not sure if the spec says itās tree scoped
khush: Want to make sure that feature is covered by the more general resolution
TabAtkins: Proposed more general resolution: 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)
So the scope of anchor-scope
is tree-scoped. Say that five times fast!
RESOLVED: 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)
The next resolution was pretty straightforward. Besides allowing a <dashed-ident>
, the anchor-scope
property can take an all
keyword, which means that all anchors are tree-scoped, while the <dashed-ident>
says that specific anchor is three-scoped. So, the question was if all
is also a tree-scoped value.
TabAtkins:
anchor-scope
, in addition to idents, can take the keyword āall
ā, which scopes all names. Should this be a tree-scoped āall
ā? (i.e. only applies to the current tree scope)TabAtkins: Proposed resolution: the ā
all
ā keyword is also tree-scoped in the same way sgtm +1, again same pattern withview-transition-group
RESOLVED: the ā
all
ā keyword is tree-scoped
The conversation switched gears toward new properties coming in the CSS Scroll Snap Module Level 2 draft, which is all about changing the userās initial scroll with CSS. Taking anexample directly from the spec, say we have an image carousel:
<div class="carousel">
<img src="https://css-tricks.com/csswg-minutes-telecon-2024-09-18/img1.jpg">
<img src="https://css-tricks.com/csswg-minutes-telecon-2024-09-18/img2.jpg">
<img src="https://css-tricks.com/csswg-minutes-telecon-2024-09-18/img3.jpg" class="origin">
<img src="https://css-tricks.com/csswg-minutes-telecon-2024-09-18/img4.jpg">
<img src="https://css-tricks.com/csswg-minutes-telecon-2024-09-18/img5.jpg">
</div>
We could start our scroll to show another image by setting itās scroll-start-targe
to auto
:
.carousel {
overflow-inline: auto;
}
.carousel .origin {
scroll-start-target: auto;
}
As of right now, the only way to complete this is using JavaScript to scroll an element into view:
document.querySelector(".origin").scrollIntoView({
behavior: "auto",
block: "center",
inline: "center"
});
The last example is probably a carousel that is only scrollable in the inline direction. Still, there are doubts as far when the container is scrollable in both the inline and block directions. As seen in the initial GitHub issue:
The scroll snap 2Ā specĀ says that when there are multiple elements that could be
scroll-start-targets
for a scroll container āuser-agents should select the one which comes first inĀ tree orderā.Selecting the first element in tree-order seems like a natural way to resolve competition between multiple targets which would be scrolled to in one particular axis but is perhaps not as flexible as might be needed for the 2d case where an author wants to scroll to one item in one axis and another item in the other axis.
And back to the CSSWG minutes:
DavidA: We have a property weāre adding called
scroll-start-target
that indicates if an element within a scroll container, then the scroll should start with that element onscreen. Question is what happens if there are multiple targets?
DavidA: Propose to do it in reverse-DOM order, this would result in the first one applied last and then be on screen. Also, should only change the scroll position if you have to.
After discussing why we have to define scroll-start-target
when we have scroll-snap-align
, the discussion went on discuss the reverse-DOM order:
fantasai: There was a bunch of discussion about regular vs reverse-DOM order. Where did we end up and why?
flackr: Currently, we expect that it scrolls to the first item in DOM order. We probably want that to still happen. That is why the proposal is to scroll to each item in sequence in reverse-DOM order.
So we are coming in reverse to scroll the element, but only as required so the following elements are showing as much as possible:
flackr: There is also the issue of nearestā¦
fantasai: Can you explain nearest?
flackr: Same as scroll into view
fantasai: ?
flackr: This is needed with you scroll multiple things into view and want to find a good position (?)
fantasai: You scroll in reverse-DOM orderā¦when you add the spec can you make it really clear that this is the end result of the algorithm?
flackr: Yes absolutely
fantasai: Otherwise it seems to make sense
And so it was resolved:
Proposed resolution 2: When
scroll-start-target
targets multiple elements, scroll to each in reverse DOM order with text to specify priority is the first item
Lastly, there was the debate about the text-underline-position
, that when set to auto
says, āThe user agent may use any algorithm to determine the underlineās position; however it must be placed at or under the alphabetic baseline.ā The discussion was about whether the auto
value should automatically adjust the underlined position to match specific language rules, for example, at the right of the text for vertical writing modes, like Japanese and Mongolian.
fantasai: The initial value of
text-underline-position
isauto
, which is defined as āfind a good place to put the underlineā.
Three options there: (1) under alphabetical baseline, (2) fully below text (good for lots-of-descenders cases), (3) for vertical text on the RHS
fantasai: auto value is defined in the spec about āhow far down below the textā, but doesnāt say things about flipping. The current spec says āat or belowā. In order to handle language-specific aspects, there is a default UA style sheet that for Chinese and Japanese and Korean there are differences for those languages. A couple of implementations do this
fantasai: Should we change the spec to mention these things?
fantasai: Or should we stick with the UA stylesheet approach?
The thing is that Chrome and Firefox already place the underline on the right in vertical Japanese when text-underline-position
is auto
.
The group was left wiuth three options:
<fantasai> A) Keep spec as-is, update Gecko + Blink to match (using UA stylesheet for language switch)
<fantasai> B) Introduce auto totext-emphasis-positio
n and use it in bothtext-emphasis-position
andtext-underline-position
to effect language switches
<fantasai> C) Adopt inconsistent behavior:text-underline-position
uses āauto
ā andtext-emphasis-position
uses UA stylesheetMany CSSWG members like Emilio Cobos, TabAtkins, Miriam Suzanne, Rachel Andrew and fantasai casted their votes, resulting in the following resolution:
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
I definitely encourage you to read at the full minutes! Or if you donāt have the time, you can thereās a list just of resolutions.