Sticky Pinning
Pin the toolbar, column header, and group header to the top of the scroll ancestor on long lists. Keeps context visible while scrolling through hundreds of rows.
The sticky prop pins one or more of the table's three
contextual layers — toolbar (L1), column header (L2), and group header (L3 when grouping is active). The pin position is offset by the
height of each preceding layer using CSS custom properties, so the layers stack naturally below
your app shell's top bar.
For tables wider than the viewport, reach for fit="viewport" (see below) — it contains both axes of scroll inside the table, so the page never scrolls sideways.
Scroll the page to see the pinned layer(s). Adjust stickyOffset to simulate a fixed app-shell top bar.
No data available |
sticky (defaults to both)
No data available |
Toolbar only
No data available |
Header only
No data available |
With stickyOffset for app-shell top bar
No data available |
The default toolbar is the SmartFilterBar. Override
it with the toolbar snippet — the custom content inherits
the same sticky wrapper.
Custom toolbar snippet
Contained scroll — fit="viewport"
Page-relative sticky pinning and in-table horizontal
scroll are mutually exclusive: a single element cannot be both a sticky-pin host and a
scroll ancestor. So with sticky="header", a table
wider than the viewport pushes its horizontal overflow onto the page — the whole layout
scrolls sideways.
fit="viewport" resolves this by making the table its
own scroll container. It is height-capped to the viewport (measured automatically — no magic max-height), the column and group headers pin to the
top of the box, and the toolbar + pagination stay fixed outside the scrolling area.
Only the rows scroll, horizontally and vertically.
Full-height list page
fit="viewport" supersedes sticky and stickyOffset (the measured top absorbs app-shell
offsets). It is mutually exclusive with virtualized, which keeps its own virtualHeight scroll box.
Caveats
- Sticky pinning anchors to the nearest scrollable ancestor. If you wrap the table in a
container with
overflow: auto/hidden, the pin will bind to that container — usually what you want inside a Drawer body, less so inside an unintentionaloverflowwrapper. - Enabling
sticky="header"or"both"disables the table's internal horizontal scrolling (the scroll area can't be both a sticky pin host AND a scroll ancestor at the same time). Very wide tables fall back to page-level horizontal scrolling — switch tofit="viewport"to contain it instead. unstyledmode strips the sticky classes — pinning is a layout function, not pure styling. Apply your own viaslotClasses.toolbar/slotClasses.theadwhen running unstyled.