← CSS scroll-marker-group modes

v154 · css · value reference

tabs mode

The generated ::scroll-marker-group “operates in ‘tabs’ mode, functioning like a tablist” — a native, declarative implementation of the WAI-ARIA Tabs Pattern: tablist/tab/tabpanel roles, a roving tab stop with arrow-key navigation, focus that moves from the active tab straight into its panel, and automatic accessibility-tree pruning of inactive panels.

Syntax

/* mode keyword combined with a position keyword (either order) */
scroll-marker-group: after tabs;
scroll-marker-group: tabs before;

tabs is one of the two mode keywords in the grammar none | [ [ before | after ] || [ links | tabs ] ] (quoted verbatim from the propdef). The spec’s value definition, in full: “The generated ::scroll-marker-group operates in ‘tabs’ mode, functioning like a tablist.” Unlike links, tabs semantics are never applied implicitly — the keyword must be present.

Source: CSS Overflow 5, valdef tabs; propdef (fetched 2026-10-04)

Inputs

tabs is a bare keyword and takes no arguments. It combines with at most one position keyword (before | after) via the || combinator, in either order, and cannot be combined with none or with links. The grammar permits scroll-marker-group: tabs with no position keyword, but the spec prose read on 2026-10-04 defines the group box’s placement only for before and after — include a position keyword in practice.

Source: CSS Overflow 5 §3.1.3; §3.1.4 ::scroll-marker-group

Outputs: roles and focus behavior

Per CSS Overflow 5 §3.1.6, when the mode is tabs:

This is the roving-tabindex tablist of the WAI-ARIA Tabs Pattern, produced declaratively: a 20-dot carousel is one tab stop, not twenty.

Source: CSS Overflow 5 §3.1.6 (quoted verbatim); explainer (Tabs Pattern mapping, a11y tree)

Errors

A CSS keyword value has no exception surface. A declaration that does not match the grammar (for example scroll-marker-group: tabs links, which repeats the mode slot) is syntactically invalid and the declaration is ignored, per standard CSS error handling; in browsers without mode support (Chrome ≤ 153, and the links/tabs keywords entirely in Firefox/Safari) the declaration likewise fails to parse and falls back to any earlier valid declaration. Feature-detect with CSS.supports("scroll-marker-group", "after tabs") and keep an earlier scroll-marker-group: after declaration as the fallback.

Source: grammar per CSS Overflow 5 §3.1.3; invalid-declaration handling per CSS Syntax 3 error handling

Context and prerequisites

scroll-marker-group applies to scroll containers (propdef “Applies to” line). Markers appear only when descendants also generate ::scroll-marker pseudo-elements with a non-none computed content value; those markers are collected into the ::scroll-marker-group of the nearest scroll container ancestor. The mode is read from the scroll-marker-group value of the group’s originating element. Works with fragmentation: markers originating from ::column pseudo-elements (column-based carousels) assign the tabpanel role to the column’s originating element. Available without flags from Chrome 154 (runtime flag CSSScrollMarkerGroupModes, status stable).

Source: CSS Overflow 5 §3.1.3; §3.1.5 ::scroll-marker; §3.1.6 (::column rule); runtime_enabled_features.json5

Lifecycle: activation

Activating a tabs-mode marker (by explicit invocation or by arrow-key focus — note that in tabs mode, focusing a marker with the arrow keys activates it) scrolls its scroll target into view (block/inline alignment “start”) and, on invocation, follows the hyperlink, updating the URL. Then, specific to tabs mode: the browser will “Retain focus on the scroll marker element” — exactly how standard tabs operate. The spec adds: “In tabs mode, if the user tabs away, the focus behavior will ensure they tab into the relevant content.” The active marker tracks scrolling (:target-current), and switching tabs swaps which panel’s content is exposed to focus and the accessibility tree.

Source: CSS Overflow 5 §3.1.9 (quoted verbatim); §3.1.8 active marker calculation

Examples

A tabbed carousel, adapted from the explainer’s tabs-mode example (live upstream demo: CodePen):

<style>
  .slides {
    /* Core tabs mode property */
    scroll-marker-group: after tabs;

    display: flex;
    overflow-x: auto;
    scroll-snap-type: x mandatory;

    &::scroll-marker-group {
      text-align: center;
      padding: 0.5rem;
    }

    & > div {
      min-width: 100%;
      scroll-snap-align: center;

      /* Individual tab markers */
      &::scroll-marker {
        content: "";
        display: inline-block;
        width: 1rem; height: 1rem;
        border-radius: 50%;
        border: 1px solid #444;
        margin: 0 0.2rem;
      }

      /* Active tab marker */
      &::scroll-marker:target-current {
        background: SelectedItem;
      }
    }
  }
</style>

<div class="slides">
  <div title="Introduction"><h3>Introduction</h3><p>Tab 1 content...</p></div>
  <div title="Focus"><h3>Focus Behaviors</h3><p>Tab 2 content...</p></div>
  <div title="Roles"><h3>Accessibility Roles</h3><p>Tab 3 content...</p></div>
</div>

The resulting accessibility tree (per the explainer) is a tabList of three tab elements with posInSet/setSize, one selected; only the active slide’s content appears as a tabPanel — inactive slides are pruned. A live interactive comparison of both modes is embedded on the feature overview.

Source: explainer gist (example adapted, labelled; a11y tree quoted); author CodePen

Compatibility

Browsertabs valueEvidence
Chrome154 (desktop, Android, WebView) — interim: no BCD entry yetChromeStatus; runtime flag stable
EdgeUnknown — no BCD record for the mode values as of 2026-10-04BCD (base property only)
FirefoxNot shipped (base property also unshipped)BCD version_added: false; no position
SafariNot shipped (base property also unshipped)BCD version_added: false; no position

In Chrome 135–153 a two-keyword declaration such as scroll-marker-group: after tabs fails to parse entirely — so on its own it would remove the marker group there. Declare the plain positional value first and layer the mode on top (see Errors).

Source: BCD; ChromeStatus API record (both fetched 2026-10-04)

Security and privacy

CSS Overflow 5 declares that it “introduces no new privacy considerations” and “no new security considerations” (Appendices C and D). The accessibility consequence specific to tabs mode is deliberate and documented: content of inactive panels is hidden from the accessibility tree and unreachable by sequential focus until its tab is activated. Do not place content that must always be reachable (status messages, consent controls, live regions) only inside an inactive panel of a tabs-mode scroll container — this placement guidance is gendn commentary derived from the spec’s tree-pruning behavior, not a normative warning.

Source: Appendix C; Appendix D; §3.1.6 (tree pruning)

Canonical sources