Vanilla Breeze

data-sticky

Activate viewport-aware sticky-positioning coordination. Set on to enable the system; the StickyManager keeps a --sticky-offset custom property in sync with the actual sticky-header height so all sticky elements (sidebar, TOC, headings) line up correctly.

Overview

The data-sticky attribute on <html> turns on VB's sticky coordination system. Behind it, StickyManager measures the live sticky-header height and writes it to --sticky-offset on :root. Every sticky sidebar, TOC, scroll-padding setting, and "scroll into view" behavior reads that variable, so they all line up correctly without you hardcoding a header offset anywhere.

On other elements, data-sticky marks the element as a sticky participant. The first <header> in the document picks it up automatically when the system is active; other elements opt in explicitly.

Usage

Two roles

OnEffect
<html data-sticky> Enables the system. StickyManager.init() runs; auto-applies data-sticky to the first <header> if not already present; sets up resize + fonts.ready + toggle listeners to keep --sticky-offset current.
<header data-sticky> Header opts in (or is auto-applied). Becomes position: sticky at top: 0; its height is what StickyManager measures.
<aside data-sticky> / <nav data-sticky> Marked as a sticky region. CSS in src/utils/sticky.css applies position: sticky with top: var(--sticky-offset) and a height constraint so the region can scroll independently if its content exceeds the viewport.
<footer data-sticky> Sticky-to-bottom variant; styles in src/native-elements/footer/styles.css.

The CSS variables it provides

VariableSet byUse for
--sticky-offsetStickyManager (px)Top offset for any other sticky element so it stays below the header.
--sticky-gap theme / authors Gap to leave above the bottom of the viewport when constraining sticky region height.

What triggers a re-measure

  • Window resizeresize listener on window (passive).
  • Fonts loadeddocument.fonts.ready resolves and triggers a re-measure (header height often changes once webfonts arrive).
  • Toggle events — any <details> opening / closing inside the header.
  • Initial mount — immediate measure plus a follow-up in the next requestAnimationFrame after layout settles.

Composition

  • <page-toc> — the TOC sidebar reads --sticky-offset for its own positioning.
  • data-page-layout — the app-shell and dashboard templates assume a sticky header.
  • scroll-padding-block-start on :root — set to var(--sticky-offset) so anchor-link jumps land below the sticky header.
  • Print stylesheet — src/utils/print.css disables sticky behavior automatically.

When NOT to use

  • Pages with no sticky chrome — the system measures and sets variables every resize; that's cheap but pointless if nothing's sticky.
  • Inside scrollable subregions — data-sticky on a child of an overflowing container won't measure correctly; coordinate with the parent's scroll state instead.