StickyAside
Main column scrolls; aside sticks under the header until the section ends. Pure CSS, server components, no scroll hijacking.
Step 1
Install the package
Add the UI kit to your app.
Step 2
Import the styles
Pull in the kit CSS once in your globals.
Step 3
Render a control
Use a primitive in your page.
Rendered example
- Who is it for?
- Developers building docs, onboarding, or pricing pages where steps scroll on one side and a summary or preview should stay visible until the section ends.
- When should I use it?
- Long step lists beside a short preview, install instructions beside a rendered example, or any section where reading order is main then aside.
- When should I pick something else?
- Pinning a single stage that crossfades through scenes — use `ScrollScenes`. A sticky bar that spans the whole viewport outside a section — use your shell header. Tall aside content without `scrollable` when you need the full block visible at once on small viewports — stack on mobile or shorten the aside.
Install or copy
This ships on npm only; there is no copy-source brick for it.
- You get
- Every component from one import, with the theme tokens included. Updates arrive with your package manager.
- You need
- React 19 and Tailwind CSS 4, for example a Next.js app created with the Tailwind option.
Install
Terminal pnpm add @zedtech/zedkit-uiLoad the styles
Tailwind does not scan node_modules, so the @source line points it at the kit's class names. The path is relative to this file.
src/app/globals.cssReplace the contents@import "tailwindcss"; @import "@zedtech/zedkit-ui/styles.css"; @source "../../node_modules/@zedtech/zedkit-ui/src/**/*.{ts,tsx}";Import and render
src/app/page.tsxReplace the contentsimport { StickyAside, Stack, Text } from "@zedtech/zedkit-ui"; import { GlassSurface } from "@zedtech/zedkit-ui/marketing"; export default function Page() { return ( <main className="p-8"> <StickyAside side="right" ratio="1/3" className="[--zk-sticky-top:7rem]"> <StickyAside.Main> <Stack gap={4}>{/* numbered steps */}</Stack> </StickyAside.Main> <StickyAside.Aside asChild> <GlassSurface padding="md"> <Text>Rendered example</Text> </GlassSurface> </StickyAside.Aside> </StickyAside> </main> ); }
Package version 1.6.2.
Usage and states
import { StickyAside, Stack, Text } from "@zedtech/zedkit-ui";
import { GlassSurface } from "@zedtech/zedkit-ui/marketing";
<StickyAside side="right" ratio="1/3" className="[--zk-sticky-top:7rem]">
<StickyAside.Main>
<Stack gap={4}>{/* numbered steps */}</Stack>
</StickyAside.Main>
<StickyAside.Aside asChild>
<GlassSurface padding="md">
<Text>Rendered example</Text>
</GlassSurface>
</StickyAside.Aside>
</StickyAside>Doc page with summary card
Write the guide
Steps stay in the main column for reading order.
import { Card, CardContent, StickyAside, Text } from "@zedtech/zedkit-ui";
// Aside on the left from the md breakpoint; stack main first on phones.
<StickyAside side="left" from="md" mobile="stack-after">
<StickyAside.Main>
<Text>Form fields…</Text>
</StickyAside.Main>
<StickyAside.Aside scrollable>
<Card>
<CardContent>Order summary</CardContent>
</Card>
</StickyAside.Aside>
</StickyAside>Wraps: position: sticky
Props
Prop
Type
Show inherited HTML attributes
Standard attributes from the underlying element. See MDN.
Prop
Type
Accessibility
DOM order is always main then aside; use mobile="before" only when the aside should appear first visually on phones. Put headings and steps in the main column; label specimen previews (for example with role="group" and aria-label). In-section links in the main column get scroll-margin-top from --zk-pin-top. With scrollable, the aside scrolls internally — keep focusable controls reachable.
Troubleshooting
Aside never sticks — check that `data-from` matches your breakpoint, the section is tall enough to scroll, and no ancestor between this root and the viewport uses `overflow: hidden|auto|scroll` or a transform. Aside hides under the site header — set `--zk-sticky-top` (or `--zk-pin-top` globally) to the header offset. Columns too narrow — pass `ratio="1/2"` or `--zk-sticky-cols`. Aside taller than the window — pass `scrollable` so it keeps sticky with an internal scroll area. Snap fights a long section — parent sections that contain `StickyAside` disable scroll-snap when `SectionScroll` is active.
title: Keep a side panel in view description: StickyAside for steps plus a sticky preview — pure CSS, no scroll hijacking.
Every UI snippet on this page is type-checked exactly as written.
Who this is for
You ship docs, onboarding, or pricing pages where one column scrolls (steps, form fields) and a short preview or summary should stay visible until the reader leaves the section.
Prerequisites
- React 19 and
@zedtech/zedkit-uistyles imported (see Theme an admin app). - A fixed or sticky site header — set
--zk-sticky-topon the layout root if the default--zk-pin-topis too short.
Steps
1. Wrap main and aside
Put scrolling content in StickyAside.Main and the panel that should stick in StickyAside.Aside. DOM order stays main then aside for screen readers.
Step 1
Install the package
Add the UI kit to your app.
Step 2
Import the styles
Pull in the kit CSS once in your globals.
Step 3
Render a control
Use a primitive in your page.
Rendered example
import { Button, Card, CardContent, Heading, StickyAside, Stack, Text } from "@zedtech/zedkit-ui";
<StickyAside className="[--zk-sticky-top:4.5rem]" side="right">
<StickyAside.Main>{/* steps */}</StickyAside.Main>
<StickyAside.Aside asChild>
<Card>
<CardContent>
<Button>Save</Button>
</CardContent>
</Card>
</StickyAside.Aside>
</StickyAside>Visible result: on wide viewports the card stays under the header while you scroll the steps; on phones the columns stack (aside after main by default).
2. Tune columns and mobile order
Use ratio="1/3" or side="left" when the sticky column should sit on the other side. Pass mobile="stack-before" when the preview should appear above the steps on narrow screens without changing DOM order.
Write the guide
Steps stay in the main column for reading order.
import { Card, CardContent, StickyAside, Text } from "@zedtech/zedkit-ui";
<StickyAside side="left" from="md" ratio="2/5" scrollable>
<StickyAside.Main>…</StickyAside.Main>
<StickyAside.Aside>
<Card>
<CardContent>
<Text variant="muted">Summary</Text>
</CardContent>
</Card>
</StickyAside.Aside>
</StickyAside>Final result
One section scrolls natively: the aside uses position: sticky inside the grid and stops at the section edge. No JavaScript runs in the layout primitive.
Troubleshooting
Aside never sticks — A parent with overflow: hidden, auto, or scroll, or a transform, sits between the layout and the viewport. Move StickyAside to the normal page flow or remove that ancestor constraint.
Panel hides under the header — Set className="[--zk-sticky-top:7rem]" (or your header offset) on StickyAside.
Tall summary clipped — Pass scrollable so the aside keeps sticky with an internal scroll area.
Next steps
- Home Get started uses the same pattern for install steps beside the rendered Save example.
- For cross-fading scenes pinned to the viewport, use Pin a stage and change scene as the page scrolls instead.