Here's the
.content wrapper with
container-type: inline-size.
Section 1
This section's id="s1" is the target of the first TOC link.
The .content wrapper has container-type: inline-size,
which is needed for the @container query below.
This card uses a container query to switch to a 2-column layout
when the container is wide enough.
This demonstrates a real-world use case for
container-type: inline-size that conflicts with
scroll-target-group.
Section 2
Scrolling here should make "Section 2" active in the sidebar TOC.
Section 3
Scrolling here should make "Section 3" active in the sidebar TOC.
Section 4
Scrolling here should make "Section 4" active in the sidebar TOC.
Section 5
Scrolling here should make "Section 5" active in the sidebar TOC.
Analysis
1. What the spec says
[OVERFLOW-5] §3.1.8
defines the active scroll marker algorithm. Step 1:
Let scroller be the nearest common ancestor scroll container
of all of the scroll marker elements in group.
The algorithm tracks the scroll position of scroller to determine which
target is in view. Nothing in the algorithm references containment or
container-type in the spec.
2. What container-type does (and does not do)
[CONDITIONAL-5] §3.1 :
container-type: inline-size — Applies style containment and
inline-size containment to the principal box, and establishes an independent
formatting context.
Crucially, container-type does not create a scroll container.
Per [OVERFLOW-3] §2 ,
a scroll container is created only when overflow computes to
scroll, auto, or hidden.
An element with container-type: inline-size and no overflow
override defaults to overflow: visible — it is not a scroll container.
3. Why this is a bug
container-type creates containment and an independent formatting context,
but per the specs above, does not make the element a scroll container
and does not alter the scroll container chain.
The active marker algorithm ([OVERFLOW-5]
§3.1.8 )
finds the scroller via "nearest common ancestor scroll container "
— containment boundaries should be transparent to this lookup.
The implementation appears to incorrectly treat the independent formatting context
as a boundary that prevents scroll position tracking of descendant target elements.
WPT scroll-target-group-* test matrix
Test
Scenario
container-type test?
001
Basic: first link is :target-current at scrollTop=0
No
002
Tracking: last link is :target-current at scrollTop=max
No
003
Coexistence with ::scroll-marker pseudo-elements
No
004
html { container: my-container / size } — size container on root
Yup, but on html (root), not intermediate ancestor
005
Invalidation: nested wrapper class removal
No
006
Invalidation: link/target DOM removal & re-insertion
No
007
Invalidation: dynamic class addition enables STG
No
008
Invalidation: dynamic class removal disables STG
No
009
Invalidation: dynamic href change to different scroller
No
010
Invalidation: dynamic href addition
No
011
Invalidation: dynamic href removal
No
012
Viewport scroller + position: fixed wrapper
No
013
Invalidation timing via click + JS assert
No
inline-crash
Inline parent of target does not crash
No
inline-targets
Inline scroll target elements
No
004 tests container: my-container / size on the
root (html) element and passes. However, no test covers
container-type: inline-size on an intermediate ancestor
of the scroll target elements. This repro demonstrates that the latter case fails.
5. Real-world impact
This bug makes it impossible to combine:
scroll-target-group for a scrollspy TOC sidebar WITH
container-type: inline-size for responsive article content
(e.g. article { container: article / inline-size } with
children using cqi units)
This is a common pattern in blog and documentation layouts.