143Art Direction Daily

Chrome 154 and Edge 154

CSS tabs finally tell a screen reader they are tabs

The markers CSS generates for a scroll-snap strip can now declare themselves a tablist, so one scroller and a few lines of CSS make a whole tabs component. Firefox 157, out today, adds a cleaner way to test for new at-rules.

Chrome 154
stable 22 Sep
Edge 154
24 Sep
Firefox 157
29 Sep, today

Carousel markers

One scroller, three modes

Linocut print of five loose index cards in vermilion over a row of five slate dots.

A plain scroll-snap strip

Panels side by side, one visible at a time. It swipes in every browser, which makes it a safe base for everything below.

scroll-snap-type: x mandatory;

Linocut print of five blank cards clipped to a vermilion string, each with a small tag.

Links mode, the default

The marker group becomes a navigation list and each marker a link, like a row of in-page anchors. Every marker is its own tab stop.

scroll-marker-group: after;

Linocut print of a slate card file drawer with one vermilion divider tab raised above the rest.

Tabs mode, new in 154

The group becomes a tablist, markers become tabs, panels become tabpanels. Pressing Tab from the active marker lands inside its panel.

scroll-marker-group: before tabs;

Live. In Chrome and Edge 154 the tab strip above is generated by CSS in tabs mode; elsewhere it is a row of anchor links over the same scroller.

Today's art direction

The page this issue is dressed as.

The Settings Pane

A SaaS settings console on cool grey, where every news item is a setting with its real value beside it.

A settings console is the page where designers build tabs and in-page navigation most often, so the issue borrows its bones: an app bar, a sticky section list, grouped rows with a label column, and a value well for each setting. The spine on the left carries the masthead the way a product carries its workspace name. Three two-colour linocut prints stand in for the three states of one scroller.

  • settings group
  • label column
  • value well
  • section nav
  • spine masthead
  • tablist
  • linocut sequence

Technique

What changed in CSS this week.

Scroll markers learn the tabs pattern

Chrome 154, stable 22 September

The scroll-marker-group property now takes two modes. In tabs mode the generated group gets the tablist role, each marker a tab, and each originating panel a tabpanel, per the Chrome 154 release notes.

Edge 154 shipped the same feature on 24 September, and its notes add the part a tabs script usually gets wrong: inactive panels drop out of the accessibility tree.

Scroller

scroll-marker-group:
  before tabs;

Underlines you can pull in from the ends

Chrome 154, stable 22 September

Text-decoration-inset reached stable Chrome, taking lengths, percentages, and separate start and end offsets. The release notes pitch it for underline reveal effects that used to need a background gradient or an extra element.

Link

text-decoration-inset:
  4px;

Tooling

Embeds and overlays that behave.

Iframes that grow to fit their document

Chrome and Edge 154

The new frame-sizing property sizes an iframe in the parent page to the embedded document, so a booking form or newsletter embed stops showing its own scrollbar.

Iframe

frame-sizing:
  content-height;

Popovers stop closing when you scroll

Chrome and Edge 154

Light dismiss for popovers and dialogs now fires on click rather than a pointerdown and pointerup pair. A touchscreen scroll gesture or a right-click no longer closes the menu the reader was using.

HTML

<div popover>

From the release notes

Content from inactive tabs is explicitly hidden from the accessibility tree.
Microsoft Edge 154 web platform release notes

Workflow

Firefox 157, released today.

Test for an at-rule before you build on it

Firefox 157, 29 September

The at-rule() function inside a supports query checks whether the browser understands an at-rule such as scope, and it also works in the supports condition of an import, per the Firefox 157 notes. A design system can now ship scoped styles behind one honest test.

Stylesheet

@supports
  at-rule(@scope) {
  …
}

Chain the scroll, skip the bounce

Firefox 157, 29 September

Overscroll-behavior gains a chain value: scrolling passes to the parent scroller at the edge, without the browser's bounce. Useful for a drawer or a settings pane nested inside a scrolling page.

Drawer

overscroll-behavior:
  chain;

Borrow this pattern

Tabs that degrade into a carousel.

Build tabs as a scroller first

What
Put each tab panel in a horizontal scroll-snap strip, then let CSS generate the tab strip in tabs mode. No script, no roles written by hand.
Where
Settings pages, pricing plan switchers, product detail tabs, any place a client asks for tabs.
Keep it honest
Browsers without the feature get a swipeable strip and a row of anchor links, so write the fallback nav in HTML and hide it only when the markers are supported.
.panes { scroll-marker-group: before tabs; }
.pane::scroll-marker { content: attr(data-label); }
.pane::scroll-marker:target-current { color: var(--ink); }

@supports selector(::scroll-marker) {
  .tabs-fallback { display: none; }
}

Prompt Lab

Export this page as a prompt for your own settings console.

Works in Claude Code, Claude Design, Beaver Builder AI, v0, Lovable, Framer AI.

Build a SaaS account settings page, the kind a freelancer ships for a client's web app: a real settings console, not a poster about one.

Structure: a 60px sticky app bar across the top (square vermilion product mark at the far left, product name, three text links at right). Below it a three-column frame: a 60px slate spine on the far left holding the workspace name, date, and plan as vertical mono text; a 232px sticky sidebar card titled "Settings" with an ordered list of section anchor links (counts in small mono at the right of each link); and a main column up to 1000px wide.

Main column: a page header (small mono uppercase kicker in vermilion, a 17ch grotesk H1, a 60ch serif deck), then one raised demo panel, then settings groups. Each settings group is a two-column grid (1fr label column, 2.35fr content): the label column holds the group h2 and a one-line description; the content column holds a white rows card with hairline-separated rows. Each row is a two-column settings row: on the left a grotesk title, a small mono source line, and one or two serif paragraphs; in a fixed 250px slot on the right a tiny uppercase key over a value well (mono, pale grey fill, 6px radius) showing the real setting value or CSS. Beside the page header, a small card of release rows (name left, date right in mono).

Tabs: build the demo panel as a horizontal scroll-snap strip of panels (each panel a 3fr/2fr grid of an image and text). Use scroll-marker-group: before tabs on the strip and ::scroll-marker with content: attr(data-label) on each panel, underlined in vermilion on :target-current. Write a fallback row of anchor links in HTML and hide it inside @supports selector(::scroll-marker).

Palette: flat cool grey ground #DCE3E7; the slate spine carries the only pattern, a 60x40px SVG tile of a toggle-switch outline in pale grey at 13 percent; panels #F7F8F7; value wells #EDF1F3; ink #1B2836; slate #22344A for the spine and one inverted "Borrow this pattern" group; muted text #4E5B68; one accent, vermilion #C73A22, used for the product mark, kicker, active tab underline, and the copy button. Italic accent #8E3322 only for one pullquote.

Type: Familjen Grotesk 500/700 for UI, titles, and the H1; Source Serif 4 for body text; IBM Plex Mono for labels, values, and code.

Images: two-colour linocut prints (vermilion and slate on off-white paper) as the tab panel images, one print per tab, one object centred per print, no readable text in any image.

Guardrails: body at least 18px with 1.65 line height and 60-75 character lines, never justified; WCAG AA contrast for every small label against its actual surface; radius 12px for cards, 6-8px for wells and buttons, no pill shapes; one soft shadow on the demo panel only; hover and focus states on every link and button at 150ms, and a prefers-reduced-motion guard; no fake toggles, fake search fields, gradients, neon, or glow; on mobile hide the sidebar, turn the spine into a horizontal strip, and stack every settings group.

Field note

A generated tabs component used to mean a script and a stack of hand-written roles an agent could get subtly wrong. With tabs mode the structure is the scroller and the semantics come from the browser, which leaves less for a prompt, or a person, to forget.

Sources

  1. Chrome 154 release notes, Chrome for Developers
  2. Microsoft Edge 154 web platform release notes, Microsoft Learn
  3. Firefox 157 release notes for developers, MDN
  4. frame-sizing, MDN
  5. scroll-marker-group, MDN
  6. ::scroll-marker, MDN