Entry 06
Indicator that slides to the active item
Use it for the underline on a tab row or the bar beside a side nav. It replaces a script that measures the active item and writes a transform and a width.
Code
<nav class="tabs">
<ul>
<li><a href="/overview" aria-current="page">Overview</a></li>
<li><a href="/pricing">Pricing and billing</a></li>
<li><a href="/docs">Docs</a></li>
</ul>
</nav>.tabs { anchor-scope: --active; }
.tabs ul {
position: relative;
display: flex;
}
.tabs [aria-current="page"] { anchor-name: --active; }
.tabs ul::after {
content: "";
position: absolute;
position-anchor: --active;
inset-block-end: 0;
inset-inline-start: anchor(start);
inline-size: anchor-size(inline);
block-size: 2px;
background: currentColor;
}
@media (prefers-reduced-motion: no-preference) {
.tabs ul::after {
transition:
inset-inline-start 0.25s var(--ease-out, ease-out),
inline-size 0.25s var(--ease-out, ease-out);
}
}Why it works, the rules and the credits
Why it works
- The anchor name sits on whichever item carries
aria-current. Move the attribute and the anchor moves with it. The same attribute tells a screen reader which item is current, so there is no separate "active" class to keep in sync. anchor()andanchor-size()resolve to the item's edge and size. A longer label, a larger font or a wrapped line needs no new measurement.- The bar is one element whose inset and size change, so a plain transition slides it.
Rules
- Keep
anchor-scopeon the component root. Without it an anchor name is global, and two navs on one page both follow the last active item. - The list needs
position: relative, so the bar is positioned against the box that holds the items. - For a vertical list swap the axes. Use
inset-block-start: anchor(top)andblock-size: anchor-size(height), and transition those two. - Give the active item a second cue such as weight or color. A browser without anchor positioning drops the
anchor()declarations and the bar has no width.
Support
- Chrome
- 131
- Firefox
- 147
- Safari
- 26
Firefox places the bar and does not slide it.
Credits
Borrowed from: Stripe, which ships the vertical form for a side nav in its home page stylesheet. The research found the rules and no page that renders the component, so this is from the stylesheet alone.
Docs: MDN: anchor-name · MDN: anchor-scope · MDN: anchor-size()