diff --git a/public/og-default.png b/public/og-default.png index bf1d4f12..ded2aecd 100644 Binary files a/public/og-default.png and b/public/og-default.png differ diff --git a/public/og/checklist.png b/public/og/checklist.png index 99d27d2d..91b48a7a 100644 Binary files a/public/og/checklist.png and b/public/og/checklist.png differ diff --git a/public/og/spec.png b/public/og/spec.png index 467432c5..d95fcbb4 100644 Binary files a/public/og/spec.png and b/public/og/spec.png differ diff --git a/public/og/spec/foundations.png b/public/og/spec/foundations.png index 07a97dc7..61734d3a 100644 Binary files a/public/og/spec/foundations.png and b/public/og/spec/foundations.png differ diff --git a/public/og/spec/foundations/anchor-positioning.png b/public/og/spec/foundations/anchor-positioning.png new file mode 100644 index 00000000..b799a060 Binary files /dev/null and b/public/og/spec/foundations/anchor-positioning.png differ diff --git a/src/content/changelog/2026-06-24-anchor-positioning.md b/src/content/changelog/2026-06-24-anchor-positioning.md new file mode 100644 index 00000000..899c541e --- /dev/null +++ b/src/content/changelog/2026-06-24-anchor-positioning.md @@ -0,0 +1,8 @@ +--- +title: New page on CSS anchor positioning +date: "2026-06-24" +type: added +relatedSlugs: [anchor-positioning] +--- + +Added a page on [CSS anchor positioning](/spec/foundations/anchor-positioning/) — the `anchor-name`, `position-anchor`, and `position-area` mechanism (CSS Anchor Positioning Module Level 1) that tethers tooltips, menus, and popovers to their trigger with no JavaScript, working across overflow and stacking boundaries. It became Baseline newly available in early 2026 and pairs with the [Popover API](/spec/foundations/popover-api/). diff --git a/src/content/spec/foundations/anchor-positioning.md b/src/content/spec/foundations/anchor-positioning.md new file mode 100644 index 00000000..08b8ab4a --- /dev/null +++ b/src/content/spec/foundations/anchor-positioning.md @@ -0,0 +1,86 @@ +--- +title: "CSS anchor positioning" +slug: anchor-positioning +category: foundations +summary: "Tether tooltips, menus, and popovers to the element that triggers them with pure CSS — no JavaScript positioning library, and it works across overflow and stacking boundaries." +status: recommended +order: 140 +appliesTo: [all] +relatedSlugs: [popover-api, native-interactive-elements, scroll-driven-animations] +updated: "2026-06-24T00:00:00.000Z" +sources: + - title: "CSS Anchor Positioning Module Level 1" + url: "https://drafts.csswg.org/css-anchor-position-1/" + publisher: "W3C CSS Working Group" + - title: "MDN — Using CSS anchor positioning" + url: "https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Anchor_positioning/Using" + publisher: "MDN" + - title: "MDN — anchor-name" + url: "https://developer.mozilla.org/en-US/docs/Web/CSS/anchor-name" + publisher: "MDN" + - title: "Introducing the CSS anchor positioning API" + url: "https://developer.chrome.com/blog/anchor-positioning-api" + publisher: "Chrome for Developers" +--- + +## What it is + +CSS anchor positioning lets one element be positioned relative to another — its _anchor_ — without the two sharing a parent or a containing block. You name an anchor, associate a positioned element with it, and place that element against the anchor's edges using CSS alone. + +Three pieces do the work: + +- `anchor-name: --trigger` registers an element as a named anchor. +- `position-anchor: --trigger` on an absolutely (or fixed) positioned element associates it with that anchor. +- The `anchor()` function and the `position-area` property place the element against the anchor's edges. + +```css +.trigger { + anchor-name: --trigger; +} + +.tooltip { + position: absolute; + position-anchor: --trigger; + position-area: top center; /* sit above, centred on the anchor */ + margin-bottom: 0.5rem; +} +``` + +`anchor-size()` sizes an element from its anchor's dimensions (a dropdown panel as wide as its button), and `@position-try` plus `position-try-fallbacks` let the element flip to a different side when it would overflow the viewport. + +## Why it matters + +- **No JavaScript positioning library.** Tooltips, menus, comboboxes, and popovers have historically needed scripts (or Popper/Floating UI) to measure the trigger and reposition on scroll and resize. The browser now does this natively, every frame. +- **It crosses boundaries.** Anchor positioning works regardless of `overflow: hidden` ancestors, `z-index`, or `transform` containing blocks — the same constraints that break hand-rolled overlays. It pairs naturally with [the Popover API](/spec/foundations/popover-api/) and top-layer elements. +- **Viewport-aware by default.** `@position-try` gives you fallback positions, so an overlay that would clip off-screen flips to a side that fits — behaviour you previously wrote and maintained by hand. + +## How to implement + +Use it to position non-blocking UI relative to its trigger. Treat it as progressive enhancement: give the element a sensible static position first, then layer anchor positioning on top. + +```css +@supports (anchor-name: --x) { + .menu { + position: absolute; + position-anchor: --menu-button; + position-area: bottom span-right; + position-try-fallbacks: flip-block, flip-inline; + } +} +``` + +`position-try-fallbacks` lists alternatives the browser tries in order until the element fits. `position-visibility: anchors-visible` hides the element when its anchor scrolls out of view, so a detached tooltip does not linger. + +## Common mistakes + +- **Forgetting to position the element.** `position-anchor` and `anchor()` only apply to an element with `position: absolute` or `fixed`. Without it, nothing moves. +- **No fallbacks.** An anchored element with a single fixed side will overflow the viewport near screen edges. Provide `position-try-fallbacks`. +- **Making it the only mechanism.** Until anchor positioning is universally available, keep a usable static fallback for browsers without support rather than leaving the overlay unpositioned. +- **Anchoring across documents.** Anchor and anchored element must be in the same document and not separated by certain layout containers — check the association actually resolves. + +## Verification + +- `@supports (anchor-name: --x)` gates the enhancement; confirm the fallback layout is acceptable on its own. +- In DevTools, inspect the anchored element and confirm its inset values resolve against the anchor. +- Scroll and resize the viewport: the element should follow its anchor and flip via fallbacks rather than clipping. +- Baseline: CSS anchor positioning became newly available across browsers in early 2026 — verify your target support before relying on it without a fallback. diff --git a/src/content/spec/foundations/popover-api.md b/src/content/spec/foundations/popover-api.md index ef573071..c6be32ac 100644 --- a/src/content/spec/foundations/popover-api.md +++ b/src/content/spec/foundations/popover-api.md @@ -6,7 +6,7 @@ summary: "Replace ARIA-puzzled JavaScript modals, menus, and tooltips with a nat status: recommended order: 130 appliesTo: [all] -relatedSlugs: [semantic-html, aria-usage, keyboard-navigation, focus-indicators] +relatedSlugs: [semantic-html, aria-usage, keyboard-navigation, focus-indicators, anchor-positioning] updated: "2026-06-08T00:00:00.000Z" sources: - title: "HTML Standard — Popover" @@ -45,7 +45,7 @@ The Popover API turns any element into a top-layer overlay using three HTML attr The `auto` value gives you light-dismiss (click outside to close) and auto-close on Escape. `manual` requires an explicit dismiss control. `hint` is for tooltip-style transient overlays that close when another `hint` opens. -CSS hooks: `:popover-open` matches an open popover, `::backdrop` styles the layer behind it, and CSS **Anchor Positioning** (`position-anchor`, `anchor()`) can position a popover relative to its trigger where supported. +CSS hooks: `:popover-open` matches an open popover, `::backdrop` styles the layer behind it, and [CSS **Anchor Positioning**](/spec/foundations/anchor-positioning/) (`position-anchor`, `anchor()`) can position a popover relative to its trigger where supported. ## Why it matters