The shadcn scroll-fade utility adds scroll-aware edge fades to any scroll container using a single Tailwind class. It shipped in June 2026 as part of the shadcn/ui chat interface release. The fade uses mask-image — so it dissolves the content itself rather than overlaying a colour — and adapts to any background without configuration. Projects initialised with npx shadcn@latest init already have it.
scroll-fade is one of many utilities and primitives in our shadcn components directory — and you can match it to your theme in the editor.
How does shadcn scroll-fade work under the hood?
scroll-fade applies a CSS mask-image that tracks scroll position via animation-timeline: scroll(self y). No JavaScript runs. No scroll listeners fire. The fade is purely CSS-driven, which means zero runtime cost and predictable output across all supported browsers.
The scroll behaviour has three states:
- At rest — the top edge is crisp, the bottom edge fades to signal more content below.
- Mid-scroll — both the top and bottom edges fade simultaneously.
- At the end — the bottom edge sharpens to confirm the last item is visible.
The default fade depth is 12% of the container height, capped at 40px. This keeps tall scroll containers subtle without any extra configuration.
No JavaScript, no listeners.
scroll-fadeuses the scroll-driven animations API. The browser handles position tracking natively. Zero runtime cost.
How to install the shadcn scroll-fade utility
If you initialised your project with npx shadcn@latest init, you already have scroll-fade. It ships with the shadcn package and the CLI imports it automatically into your global CSS file. There is nothing else to do.
For projects set up without the CLI, install the package manually:
Then import the shared utilities in your global CSS file:
That is the entire installation. There is no component to register and no components.json entry to add.
No CLI add command.
scroll-fadeis a CSS utility, not a component. Runningshadcn add scroll-fadeis not needed and will not work. The utility loads automatically viashadcn/tailwind.css.
Full shadcn scroll-fade class reference
The utility ships 13 Tailwind utility classes. Each targets a specific scroll axis or edge.
| Class | Axis | What it does |
|---|---|---|
scroll-fade | Y — vertical | Fades top and bottom edges. Tracks vertical scroll position. |
scroll-fade-y | Y — vertical | Identical to scroll-fade. Explicit vertical axis variant. |
scroll-fade-x | X — horizontal | Fades left and right edges. Tracks horizontal scroll position. |
scroll-fade-t | Y — top only | Fades the top edge only. |
scroll-fade-b | Y — bottom only | Fades the bottom edge only. |
scroll-fade-l | X — left only | Fades the left edge. Physical — does not mirror in RTL. |
scroll-fade-r | X — right only | Fades the right edge. Physical — does not mirror in RTL. |
scroll-fade-s | X — start edge | Fades the inline-start edge. Mirrors automatically in RTL. |
scroll-fade-e | X — end edge | Fades the inline-end edge. Mirrors automatically in RTL. |
scroll-fade-<number> | Size modifier | Sets fade depth on spacing scale. scroll-fade-8 = 32px. |
scroll-fade-[<value>] | Arbitrary size | Sets any custom depth. scroll-fade-[60px]. |
scroll-fade-{t,b,s,e}-<number> | Per-edge size | Sets depth on one edge only. scroll-fade-b-8. |
scroll-fade-none | Disable | Removes the fade mask entirely. |
Apply the class to the element that has overflow-y-auto or overflow-x-auto — not to a wrapper around it.
Vertical list with scroll-fade
Horizontal tags with scroll-fade-x
When to use each shadcn scroll-fade variant
Use the right variant for your scroll axis. The wrong class on the wrong axis produces no visible output.
Use scroll-fade or scroll-fade-y on any vertically scrolling list. Good candidates include sidebar navigation, command palettes, dropdown menus, and long content feeds. Long dropdowns get the same treatment — the shadcn select component is a natural place to apply it. Sidebar navigation is one of the most common vertical list patterns in production apps. If you are building a collapsible sidebar, see our guide on the shadcn resizable sidebar component for the full implementation pattern.
Use scroll-fade-x on horizontal containers like tag rows, chip selectors, and horizontal feature lists. The horizontal fade is direction-aware. In RTL layouts, the crisp edge and fade follow the reading direction automatically — no extra classes needed.
Use edge-specific variants when only one boundary matters. For example, use scroll-fade-b on a top-loaded feed so only the bottom edge fades to signal more content. Use scroll-fade-t on a bottom-anchored chat thread to signal history above.
Use scroll-fade-s and scroll-fade-e instead of scroll-fade-l and scroll-fade-r when building RTL-compatible layouts. The logical variants mirror automatically. The physical variants (l and r) stay fixed regardless of text direction.
How to use shadcn scroll-fade with ScrollArea and MessageScroller
scroll-fade works on any element with overflow. However, two shadcn/ui components pair with it directly in production: ScrollArea and MessageScroller.
Common mistake — apply to the inner viewport, not the outer wrapper. The outer wrapper holds the border and background. Placing
scroll-fadeon it dissolves the card edge instead of the content.
The content fades at the edges. Border stays crisp.
With MessageScroller:
MessageScroller is the scroll container by design. Apply scroll-fade directly to it — no inner wrapper needed.
This is the most common production use case for the shadcn fade effect. Chat interfaces with streaming replies benefit most. The bottom edge fades while the user reads, then sharpens when there is nothing more to show. For full chat implementation patterns including message bubbles and typing indicators, see our shadcn chat UI guide.
How to control the shadcn scroll-fade depth
The default fade depth is 12% of the container height, capped at 40px. For most containers this requires no adjustment. However, two situations call for a custom size.
scroll-fade — 12% of height, capped at 40px
You can also target individual edges with size modifiers. scroll-fade-b-8 sets only the bottom fade depth to 32px while leaving the top edge at its default. This is useful when the top of a list always starts flush and only the bottom needs a fade cue.
Does shadcn scroll-fade show a fade when content does not overflow?
No. If the content fits within the container without scrolling, no fade appears. You can therefore apply scroll-fade to every list in your app defensively — without checking whether each one actually overflows. The utility handles the conditional logic in CSS with no JavaScript detection needed.
Content fits — no fade shown. Safe to apply unconditionally.
This removes the need for useRef plus useEffect scroll detection that developers previously wrote to conditionally render gradient overlays. One class handles both the overflowing and non-overflowing cases correctly.
shadcn scroll-fade vs a CSS gradient overlay: what is the difference?
Before scroll-fade, the standard approach was an absolutely positioned div with a gradient background colour that matched the container. That pattern has three problems: it breaks on non-solid backgrounds, it is always visible regardless of scroll position, and it requires manual RTL adjustments.
| Approach | Background-independent | Scroll-aware | Zero JS | RTL support |
|---|---|---|---|---|
| CSS gradient overlay | Must match background | Always visible | Yes | Manual |
| JS scroll listener + overlay | Must match background | Yes | No | Manual |
scroll-fade utility | Uses mask-image | CSS scroll timeline | Yes | Logical variants |
The gradient overlay approach breaks on non-solid backgrounds — glassmorphism panels, images behind cards, and dark mode transitions all require separate gradient colour values per context. scroll-fade uses mask-image instead. It dissolves the content itself, so it adapts to any background with no configuration.
The JS scroll listener approach adds runtime cost and can cause layout thrash on heavy lists. scroll-fade has zero runtime cost. It is entirely CSS-driven via the scroll-driven animations API, so the browser handles position tracking natively.
How to use shadcn scroll-fade on a sidebar navigation list
A sidebar nav list is the most common vertical scroll pattern in production apps. Nav items overflow when a project has many routes — settings panels, admin dashboards, and docs sites all hit this. scroll-fade signals overflowing items without adding a scrollbar that breaks the sidebar's visual edge.
Apply scroll-fade directly to the scrollable nav container. Keep the sidebar wrapper clean — border, background, and fixed height live on the outer element. The fade dissolves the nav items themselves.
Fixed header and footer, scrollable middle. Structure the sidebar as a flex column with
h-screen. The header and footer are fixed. Only the middle<nav>getsflex-1 overflow-y-autoandscroll-fade. This is the correct pattern for any app shell sidebar.
If the nav items fit without overflowing, no fade appears — safe to apply unconditionally. For the full sidebar implementation with collapsible groups and resize handles, see the collapsible sidebar pattern.
How to use shadcn scroll-fade in a command palette
A command palette (built with the shadcn Command component) shows a filtered results list that can grow to any length. Without a fade, the list either clips abruptly at a hard height or forces a visible scrollbar that looks out of place inside a floating panel.
scroll-fade dissolves the bottom of the list naturally, signalling more results without breaking the panel's visual container.
Pages
Actions
Help
Apply to
CommandList, notCommand.CommandListis the scroll container.Commandis the outer wrapper that holds the input and the list together. Applyingscroll-fadeto the outerCommandwraps the input field in the fade — which is wrong. Apply it toCommandListonly.
The max-h-80 cap keeps the palette compact. As the user types and filters results, the list height adjusts and the fade appears only when results overflow the cap.
How to use shadcn scroll-fade in a chat thread
A chat thread is the canonical use case scroll-fade shipped for. The thread anchors to the bottom while streaming. History accumulates above. scroll-fade-t fades the top edge to signal history above — while leaving the bottom edge crisp, because the live reply is what the user is reading.
Use
scroll-fade-t, notscroll-fade.scroll-fadefades both edges. In a chat thread the bottom edge should always be crisp — it is the live reply the user is watching.scroll-fade-tfades the top edge only, signalling history above while keeping the active reply fully visible at the bottom.
The fade disappears when the thread is scrolled to the very top, because there is no hidden history above. It reappears as the user scrolls down and history accumulates above the viewport. For the complete chat implementation with typing indicators, timestamps, and file attachments, see our shadcn chat UI examples.
How to use shadcn scroll-fade on a horizontal tag carousel
Horizontal chip rows and tag selectors overflow on narrow viewports and inside constrained containers like card sidebars and filter bars. A scrollbar on a chip row looks wrong — it is too heavy for the visual weight of the element. scroll-fade-x hints at overflow without a scrollbar.
Selected: React, Next.js
shrink-0on every chip,pb-1on the container. Withoutshrink-0, flex children compress instead of overflowing. Thepb-1bottom padding prevents the scrollbar (on systems that show one) from clipping the chip border. Neither affects thescroll-fade-xbehaviour.
This pattern works identically for horizontal nav tabs, breadcrumb rows, and step indicators in multi-step forms. The fade is RTL-aware — on RTL layouts the crisp edge automatically shifts to the right and the fade appears on the left, with no extra classes.
How to use shadcn scroll-fade inside a modal content list
A modal with a long list — search results, team member selectors, notification feeds — needs scroll handling that does not fight the modal's own overflow. The standard mistake is applying overflow to the DialogContent itself, which breaks focus trapping and the close animation.
The correct pattern: fixed-height content area inside the dialog, with scroll-fade on that inner container only.
Add team members
Do not put
overflow-y-autoonDialogContent. Radix Dialog manages its own overflow for focus trapping and scroll locking. Addingoverflow-y-autotoDialogContentbreaks both. Instead, usemax-h-[85vh] flex flex-colonDialogContent, then putScrollArea+scroll-fadeon the inner list only.
The max-h-[85vh] cap on DialogContent keeps the modal off the viewport edges on short screens. The flex-1 on ScrollArea lets the list fill whatever space remains between the fixed header and footer.
Frequently asked questions about shadcn scroll-fade
Build faster with shadcn/ui templates
Utilities like scroll-fade are most useful when the rest of your UI is already in good shape. If you are building a landing page or SaaS product and want a production-ready starting point built on Next.js App Router, Tailwind CSS, and TypeScript, browse the shadcn/ui landing page templates at ShadcnDeck. Every template uses shadcn/ui natively, so utilities like scroll-fade drop straight in without any compatibility work. Free templates with full source code are also available — no attribution required.




