<arc-sticky> Overview
Guidelines
When to use
- Use for section headers in long scrollable lists or content areas
- Use for toolbar rows that should stick below a fixed top bar (set offset to top bar height)
- Style the stuck state via the `[stuck]` attribute selector for shadows, borders, or background changes
- Listen for the `arc-stuck` event when you need to update application state on stick/unstick
- Set offset to match any fixed headers above the sticky element to avoid overlap
When not to use
- Do not use Sticky for elements that should be `position: fixed` — Sticky respects scroll context
- Do not nest Sticky inside another Sticky in the same scroll container
- Do not rely on Sticky for critical layout structure — it is a progressive enhancement
- Do not set offset to a negative value — the element will stick above the viewport edge
- Do not use Sticky when the parent container does not have overflow scroll — sticky has no effect without a scrollable ancestor
Features
- CSS `position: sticky` with configurable `top` offset via the `offset` prop
- IntersectionObserver-based stuck detection — no scroll event listeners
- Sets a `stuck` boolean attribute on the host when the element is stuck
- Fires `arc-stuck` custom event with `{ stuck: boolean }` detail for state synchronization
- Performant sentinel technique works with many sticky elements on the same page
- CSS part: `sticky` for targeted ::part() styling
- Works inside any scrollable container, not just the viewport
Preview
Scroll down to see the sticky header
Sticky Section Header
List item 1
List item 2
List item 3
List item 4
List item 5
List item 6
List item 7
List item 8
Usage
This component requires JavaScript. No pure HTML/CSS version is available — use the Web Component directly or a framework wrapper.
<arc-sticky offset="0px">
<div class="section-header">Section Title</div>
</arc-sticky>
<style>
arc-sticky[stuck] .section-header {
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
background: var(--bg-surface-overlay);
backdrop-filter: blur(8px);
}
</style>
<script>
const sticky = document.querySelector('arc-sticky');
sticky.addEventListener('arc-stuck', (e) => {
console.log('Stuck:', e.detail.stuck);
});
</script> import { Sticky } from '@arclux/arc-ui-react';
function StickyHeader() {
return (
<Sticky offset="64px" onArcStuck={(e) => console.log('Stuck:', e.detail.stuck)}>
<div className="section-header">Section Title</div>
</Sticky>
);
} <script setup>
import { Sticky } from '@arclux/arc-ui-vue';
function onStuck(e: CustomEvent) {
console.log('Stuck:', e.detail.stuck);
}
</script>
<template>
<Sticky offset="64px" @arc-stuck="onStuck">
<div class="section-header">Section Title</div>
</Sticky>
</template> <script>
import { Sticky } from '@arclux/arc-ui-svelte';
</script>
<Sticky offset="64px" on:arc-stuck={(e) => console.log('Stuck:', e.detail.stuck)}>
<div class="section-header">Section Title</div>
</Sticky> import { Component } from '@angular/core';
import { Sticky } from '@arclux/arc-ui-angular';
@Component({
imports: [Sticky],
template: `
<Sticky offset="64px" (arcStuck)="onStuck($event)">
<div class="section-header">Section Title</div>
</Sticky>
`,
})
export class StickyHeaderComponent {
onStuck(e: CustomEvent) {
console.log('Stuck:', e.detail.stuck);
}
} import { Sticky } from '@arclux/arc-ui-solid';
function StickyHeader() {
return (
<Sticky offset="64px" onArcStuck={(e) => console.log('Stuck:', e.detail.stuck)}>
<div class="section-header">Section Title</div>
</Sticky>
);
} import { Sticky } from '@arclux/arc-ui-preact';
function StickyHeader() {
return (
<Sticky offset="64px" onArcStuck={(e) => console.log('Stuck:', e.detail.stuck)}>
<div class="section-header">Section Title</div>
</Sticky>
);
} API
| Prop | Type | Default | Description |
|---|---|---|---|
offset | string | '0px' | The CSS `top` value for sticky positioning. Set to "64px" to stick below a 64px top bar, or "0px" to stick flush with the viewport/scroll container edge. |
stuck | boolean | false | Read-only attribute set by the IntersectionObserver when the element is currently stuck. Use the `[stuck]` CSS selector to style the stuck state. |
Events
| Event | Description |
|---|---|
arc-stuck | Fired when the stuck state changes. Event detail contains `{ stuck: boolean }` indicating whether the element is currently stuck. |
See Also
- Top Bar Fixed header bar that anchors every page with a brand slot on the left, an optional center navigation area, and a right-aligned actions region for user controls, search, and settings.
- Toolbar Horizontal toolbar with start, center, and end slots.
- Scroll Spy Tracks scroll position and highlights the active navigation link.