v154 · css · carousels & accessibility
CSS scroll-marker-group modes
The scroll-marker-group property grows two mode keywords, links and tabs. One property value now decides whether a carousel's dots behave like a list of in-page links (navigation + link roles, every dot a tab stop) or like a real WAI-ARIA tablist (roving focus, arrow keys, inactive panels pruned from the accessibility tree) — semantics that used to take a page of carefully-maintained ARIA JavaScript.
concepts
-
Mode switcher
One live carousel, every grammar variant of
scroll-marker-groupon a switch: position only, position + mode, and the final v154 mode-only forms. A supports matrix and a computed-value readback show exactly which grammar generation your browser parses. -
Tabbed carousel
The product use case: a labelled, styled tabbed carousel built from
scroll-marker-group: after tabs,::scroll-marker { content: attr(data-label) }and:target-current— no ARIA attributes, no tab-switching script. -
Focus-order journal
Two identical carousels, one in
linksmode and one intabsmode, with a live journal that records what your keyboard actually does: which element holds focus, which keys move it, and whether the dots are sequential tab stops or a roving-focus group. -
The ARIA tabs migration
A classic hand-rolled WAI-ARIA tabs widget — roving tabindex, arrow-key handler,
aria-selectedbookkeeping, all working — next to the CSStabs-mode equivalent, with a line-by-line accounting of what the one keyword deletes. -
Column pager
The advanced composition from the spec text itself:
::column::scroll-markerpagination over a multi-column article intabsmode, where the column fragments become the tabpanels. Resize the type and the pager re-derives itself.
why it shipped
Chrome 135's CSS carousel primitives (::scroll-marker-group, ::scroll-marker, :target-current) made the dots free, but left one hard question open: what should the dots be to a keyboard and a screen reader? A photo carousel's dots want to be a tablist with roving focus; a table-of-contents wants each marker to be an ordinary link and a tab stop. No single default serves both.
Chrome 154 resolves it in the property grammar: scroll-marker-group: none | [ [ before | after ] || [ links | tabs ] ]. In links mode (the default) the group is a navigation landmark of link-role markers, all sequential tab stops, and activating one moves the sequential-focus starting point to the target — exactly like clicking <a href="#target">. In tabs mode the group is a tablist of tab-role markers with roving tabindex and arrow-key navigation, originating elements get the tabpanel role, Tab from the active marker enters the active panel, and inactive panels are pruned from the accessibility tree with no interactivity: inert bookkeeping.
research record — use cases & exact surface
- Exact grammar (spec §3.1.3):
scroll-marker-group: none | [ [ before | after ] || [ links | tabs ] ]— position and mode combine in any order, either may stand alone;linksis the default mode when omitted. - Mode contracts (spec §3.1.6): links →
navigation/linkroles, all markers tab stops, originating elements untouched; tabs →tablist/tab/tabpanelroles, focusgroup with roving tabindex, marker is a focus-navigation-scope owner, inactive-panel accessibility-tree pruning. When the originating element is a::column, thetabpanelrole goes to the column's originating element. - Runtime flag:
CSSScrollMarkerGroupModesinruntime_enabled_features.json5(statusstablefor 154; grammar finalised in csswg-drafts#12122). Depends on the Chrome 135CSSPseudoScrollMarkersprimitives. - Use-case portfolio: grammar/inspection (mode-switcher), product tablist carousel (tabbed-carousel), keyboard-contract observation (focus-order-journal), migration from hand-rolled ARIA (aria-tabs-migration),
::columncomposition (column-pager). All five angles built.