Vize

Sticky

Headless sticky/affix wrapper that pins with native position: sticky and reports stuck state.

Package @vizejs/ui/sticky
Maturity stable
Own the source vize lib pull sticky
Requires measure
Aliases sticky, affix, sticky header, pinned
Covers CSS position: sticky, Ant Design Affix, IntersectionObserver stuck detection

Usage

import { Sticky, Affix } from "@vizejs/ui/sticky";

Or copy the source into your project with vize lib pull sticky (see Source Distribution).

API

Sticky

Source: src/families/layout/sticky/sticky.vue

Props

Prop Type Default Description
as keyof HTMLElementTagNameMap "div" Native element rendered as the sticky box, for example header or nav.
side StickySide "top" Edge the element pins to.
offset number 0 Distance in CSS pixels between the pinned edge and the scroll container edge.
root HTMLElement | null null Scroll container used to detect the stuck state. null uses the viewport.
disabled boolean false Render in normal flow without position: sticky or stuck detection.

Events

Event Payload Description
stuck-change [stuck: boolean] Fired when the element becomes pinned or releases.

Slots

Slot Slot props Description
default StickySlotState Sticky contents. Receives the stuck state.

Exposed

Member Type Description
stuck boolean Whether the element is currently pinned at its offset.
state StickyState Stable state token for styling and tests.
side StickySide Pinned edge.
element HTMLElement | null Rendered sticky element or component instance root.
refresh () => boolean Re-read geometry and update stuck immediately. Returns the new value.

Affix

Source: src/families/layout/sticky/sticky.vue

Props

Prop Type Default Description
as keyof HTMLElementTagNameMap "div" Native element rendered as the sticky box, for example header or nav.
side StickySide "top" Edge the element pins to.
offset number 0 Distance in CSS pixels between the pinned edge and the scroll container edge.
root HTMLElement | null null Scroll container used to detect the stuck state. null uses the viewport.
disabled boolean false Render in normal flow without position: sticky or stuck detection.

Events

Event Payload Description
stuck-change [stuck: boolean] Fired when the element becomes pinned or releases.

Slots

Slot Slot props Description
default StickySlotState Sticky contents. Receives the stuck state.

Exposed

Member Type Description
element Readonly<ShallowRef<HTMLElement | null>> Template ref to the rendered root element.
refresh —
side —
state —
stuck —

Behavior

Normative behavior for @vizejs/ui/sticky (Sticky, alias Affix). sticky.vue pins with native position: sticky — no scroll listeners move the element — and only observes geometry to report whether it is currently pinned. Every row is proven by the named test.

State x input Observable outcome Proven by
any render The native element (as) carries position: sticky, the side inset, --vize-sticky-offset, data-side, and data-state. renders native sticky positioning with offset variables and slot state
mounted An IntersectionObserver watches the element with a root margin that trims offset + 1 px from the pinned edge. renders native sticky positioning with offset variables and slot state
box rests on its offset line data-stuck="true", data-state="stuck", and stuck-change fires once with true. reports stuck when the box rests on its offset line and releases after
box sits below the line or scrolled away with its block data-stuck is removed and stuck-change fires once with false. reports stuck when the box rests on its offset line and releases after
side="bottom" with a custom root Geometry is measured against the container bottom and the observer uses that root. bottom stickiness measures against the container bottom edge
disabled Sticky positioning is removed and the observer disconnects; re-enabling reconnects with the current offset. disabled stickiness drops positioning and observation
expose refresh() Re-reads geometry synchronously and returns the new stuck value. expose refresh re-reads geometry on demand
geometry helpers isStickyStuck and stickyRootMargin describe the one-pixel pinned band on both edges. geometry helpers describe the pinned band on both edges
SSR Server markup is byte-identical, includes the sticky style, and never reports stuck. renders byte-identical sticky markup without stuck state on the server
hydration The server element is reused with zero warnings; observation starts after mount. hydrates the server box without diagnostics
public types Side, state, native tag, and numeric offset are closed contracts. src/families/layout/sticky/sticky.types.test-d.ts
DOM/SSR/Vapor sticky.vue compiles in every renderer lane. scripts/check-renderers.ts

Parts And Data

Target Public contract
Root part="root", data-vize-ui="sticky", data-side, data-state, data-stuck, data-disabled, --vize-sticky-offset

Sticky ships no stylesheet beyond the inline sticky declaration required for the behavior.