Scroll Fade
The scroll fade masks the edges of a scroller so content melts away instead of clipping, hinting that there is more to scroll. Use it for long lists, chat feeds, and horizontal tag rows, anywhere clipped content should read as scrollable.
<div class="mx-auto w-full max-w-xs overflow-hidden rounded-2xl border">
<div class="scroll-fade scrollbar-none h-72 overflow-y-auto">
<div class="flex flex-col gap-1.5 p-1.5">
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 1</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 2</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 3</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 4</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 5</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 6</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 7</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 8</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 9</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 10</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 11</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 12</div>
</div>
</div>
</div>Usage
Add scroll-fade to any vertical scroller; use the directional variants for horizontal scrollers or a single edge. The fades follow the scroll position, so an edge only fades while more content lies in that direction. The fade size defaults to 12% of the scroller, capped at 2.5rem; override it with the size utilities, like scroll-fade-16 for a spacing-scale value or scroll-fade-[15%] for an arbitrary one. In browsers without scroll-driven animations, the edges fade statically instead, no JavaScript involved.
<div class="scroll-fade h-64 overflow-y-auto">
<!-- long content -->
</div>Examples
No overflow, no fade
The fades are driven by the scroll position, so a scroller whose content fits shows no fade at all.
<div class="mx-auto w-full max-w-xs overflow-hidden rounded-2xl border">
<div class="scroll-fade scrollbar-none overflow-y-auto">
<div class="flex flex-col gap-1.5 p-1.5">
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 1</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 2</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 3</div>
</div>
</div>
</div>Horizontal scrolling
Add scroll-fade-x to a horizontal scroller. The fades follow the reading direction.
<div class="mx-auto w-full max-w-xs overflow-hidden rounded-2xl border">
<div class="scroll-fade-x scrollbar-none overflow-x-auto">
<div class="flex w-max gap-1.5 p-1.5">
<div class="shrink-0 rounded-lg bg-muted px-3 py-2.5 text-sm">Design</div>
<div class="shrink-0 rounded-lg bg-muted px-3 py-2.5 text-sm">
Engineering
</div>
<div class="shrink-0 rounded-lg bg-muted px-3 py-2.5 text-sm">
Marketing
</div>
<div class="shrink-0 rounded-lg bg-muted px-3 py-2.5 text-sm">
Product
</div>
<div class="shrink-0 rounded-lg bg-muted px-3 py-2.5 text-sm">
Research
</div>
<div class="shrink-0 rounded-lg bg-muted px-3 py-2.5 text-sm">Sales</div>
<div class="shrink-0 rounded-lg bg-muted px-3 py-2.5 text-sm">
Support
</div>
<div class="shrink-0 rounded-lg bg-muted px-3 py-2.5 text-sm">
Operations
</div>
<div class="shrink-0 rounded-lg bg-muted px-3 py-2.5 text-sm">
Finance
</div>
<div class="shrink-0 rounded-lg bg-muted px-3 py-2.5 text-sm">Legal</div>
<div class="shrink-0 rounded-lg bg-muted px-3 py-2.5 text-sm">People</div>
<div class="shrink-0 rounded-lg bg-muted px-3 py-2.5 text-sm">
Security
</div>
</div>
</div>
</div>Edge fades
Fade a single edge with the directional variants: scroll-fade-t and scroll-fade-b for vertical scrollers, scroll-fade-s and scroll-fade-e for horizontal ones.
<div class="mx-auto flex w-full max-w-xs min-w-0 flex-col gap-6">
<div class="flex flex-col gap-3">
<div class="overflow-hidden rounded-2xl border">
<div class="scroll-fade-t scrollbar-none h-36 overflow-y-auto">
<div class="flex flex-col gap-1.5 p-1.5">
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">
Inbox triage
</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">
Design review
</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">
API contract
</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">QA pass</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">
Launch notes
</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">
Metrics follow-up
</div>
</div>
</div>
</div>
<p class="text-center font-mono text-xs text-muted-foreground">
scroll-fade-t
</p>
</div>
<div class="flex flex-col gap-3">
<div class="overflow-hidden rounded-2xl border">
<div class="scroll-fade-b scrollbar-none h-36 overflow-y-auto">
<div class="flex flex-col gap-1.5 p-1.5">
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">
Inbox triage
</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">
Design review
</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">
API contract
</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">QA pass</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">
Launch notes
</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">
Metrics follow-up
</div>
</div>
</div>
</div>
<p class="text-center font-mono text-xs text-muted-foreground">
scroll-fade-b
</p>
</div>
<div class="flex flex-col gap-3">
<div class="overflow-hidden rounded-2xl border">
<div class="scroll-fade-s scrollbar-none overflow-x-auto">
<div class="flex w-max gap-1.5 p-1.5">
<div class="shrink-0 rounded-lg bg-muted px-3 py-2.5 text-sm">
Design
</div>
<div class="shrink-0 rounded-lg bg-muted px-3 py-2.5 text-sm">
Engineering
</div>
<div class="shrink-0 rounded-lg bg-muted px-3 py-2.5 text-sm">
Marketing
</div>
<div class="shrink-0 rounded-lg bg-muted px-3 py-2.5 text-sm">
Product
</div>
<div class="shrink-0 rounded-lg bg-muted px-3 py-2.5 text-sm">
Research
</div>
<div class="shrink-0 rounded-lg bg-muted px-3 py-2.5 text-sm">
Sales
</div>
</div>
</div>
</div>
<p class="text-center font-mono text-xs text-muted-foreground">
scroll-fade-s
</p>
</div>
<div class="flex flex-col gap-3">
<div class="overflow-hidden rounded-2xl border">
<div class="scroll-fade-e scrollbar-none overflow-x-auto">
<div class="flex w-max gap-1.5 p-1.5">
<div class="shrink-0 rounded-lg bg-muted px-3 py-2.5 text-sm">
Design
</div>
<div class="shrink-0 rounded-lg bg-muted px-3 py-2.5 text-sm">
Engineering
</div>
<div class="shrink-0 rounded-lg bg-muted px-3 py-2.5 text-sm">
Marketing
</div>
<div class="shrink-0 rounded-lg bg-muted px-3 py-2.5 text-sm">
Product
</div>
<div class="shrink-0 rounded-lg bg-muted px-3 py-2.5 text-sm">
Research
</div>
<div class="shrink-0 rounded-lg bg-muted px-3 py-2.5 text-sm">
Sales
</div>
</div>
</div>
</div>
<p class="text-center font-mono text-xs text-muted-foreground">
scroll-fade-e
</p>
</div>
</div>Fade size
Size utilities change how far the fade reaches: scroll-fade-{n} takes a spacing-scale value or an arbitrary length, and the per-edge forms like scroll-fade-b-8 size one edge on its own.
<div class="mx-auto flex w-full max-w-xs flex-col gap-6">
<div class="flex flex-col gap-3">
<div class="overflow-hidden rounded-2xl border">
<div
class="scroll-fade scrollbar-none h-48 overflow-y-auto scroll-fade-4"
>
<div class="flex flex-col gap-1.5 p-1.5">
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 1</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 2</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 3</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 4</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 5</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 6</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 7</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 8</div>
</div>
</div>
</div>
<p class="text-center font-mono text-xs text-muted-foreground">
scroll-fade-4
</p>
</div>
<div class="flex flex-col gap-3">
<div class="overflow-hidden rounded-2xl border">
<div
class="scroll-fade scrollbar-none h-48 overflow-y-auto scroll-fade-24"
>
<div class="flex flex-col gap-1.5 p-1.5">
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 1</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 2</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 3</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 4</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 5</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 6</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 7</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 8</div>
</div>
</div>
</div>
<p class="text-center font-mono text-xs text-muted-foreground">
scroll-fade-24
</p>
</div>
</div>Disabling the fade
Add scroll-fade-none to remove the fade, for example at a breakpoint where the layout no longer scrolls.
<div class="mx-auto flex w-full max-w-xs min-w-0 flex-col gap-6">
<div class="flex flex-col gap-3">
<div class="overflow-hidden rounded-2xl border">
<div class="scroll-fade scrollbar-none h-48 overflow-y-auto">
<div class="flex flex-col gap-1.5 p-1.5">
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 1</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 2</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 3</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 4</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 5</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 6</div>
</div>
</div>
</div>
<p class="text-center font-mono text-xs text-muted-foreground">
scroll-fade
</p>
</div>
<div class="flex flex-col gap-3">
<div class="overflow-hidden rounded-2xl border">
<div
class="scroll-fade scroll-fade-none scrollbar-none h-48 overflow-y-auto"
>
<div class="flex flex-col gap-1.5 p-1.5">
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 1</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 2</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 3</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 4</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 5</div>
<div class="rounded-lg bg-muted px-3 py-2.5 text-sm">Item 6</div>
</div>
</div>
</div>
<p class="text-center font-mono text-xs text-muted-foreground">
scroll-fade scroll-fade-none
</p>
</div>
</div>RTL
Add dir="rtl" to any parent element, typically <html>, to render right-to-left. The inline fades of scroll-fade-x, scroll-fade-s, and scroll-fade-e mirror automatically. See the RTL guide for details.
<div
id="scroll-fade-rtl-demo"
dir="rtl"
class="mx-auto w-full max-w-xs overflow-hidden rounded-2xl border"
>
<div class="scroll-fade-x scrollbar-none overflow-x-auto">
<div class="flex w-max gap-1.5 p-1.5">
<div
class="shrink-0 rounded-lg bg-muted px-3 py-2.5 text-sm"
data-i18n="design"
>
التصميم
</div>
<div
class="shrink-0 rounded-lg bg-muted px-3 py-2.5 text-sm"
data-i18n="engineering"
>
الهندسة
</div>
<div
class="shrink-0 rounded-lg bg-muted px-3 py-2.5 text-sm"
data-i18n="marketing"
>
التسويق
</div>
<div
class="shrink-0 rounded-lg bg-muted px-3 py-2.5 text-sm"
data-i18n="product"
>
المنتج
</div>
<div
class="shrink-0 rounded-lg bg-muted px-3 py-2.5 text-sm"
data-i18n="research"
>
الأبحاث
</div>
<div
class="shrink-0 rounded-lg bg-muted px-3 py-2.5 text-sm"
data-i18n="sales"
>
المبيعات
</div>
<div
class="shrink-0 rounded-lg bg-muted px-3 py-2.5 text-sm"
data-i18n="support"
>
الدعم
</div>
<div
class="shrink-0 rounded-lg bg-muted px-3 py-2.5 text-sm"
data-i18n="operations"
>
العمليات
</div>
<div
class="shrink-0 rounded-lg bg-muted px-3 py-2.5 text-sm"
data-i18n="finance"
>
المالية
</div>
<div
class="shrink-0 rounded-lg bg-muted px-3 py-2.5 text-sm"
data-i18n="legal"
>
الشؤون القانونية
</div>
</div>
</div>
</div>
<script>
const translations = {
ar: {
dir: "rtl",
design: "التصميم",
engineering: "الهندسة",
marketing: "التسويق",
product: "المنتج",
research: "الأبحاث",
sales: "المبيعات",
support: "الدعم",
operations: "العمليات",
finance: "المالية",
legal: "الشؤون القانونية",
},
he: {
dir: "rtl",
design: "עיצוב",
engineering: "הנדסה",
marketing: "שיווק",
product: "מוצר",
research: "מחקר",
sales: "מכירות",
support: "תמיכה",
operations: "תפעול",
finance: "כספים",
legal: "משפטי",
},
en: {
dir: "ltr",
design: "Design",
engineering: "Engineering",
marketing: "Marketing",
product: "Product",
research: "Research",
sales: "Sales",
support: "Support",
operations: "Operations",
finance: "Finance",
legal: "Legal",
},
};
window.addEventListener("message", (e) => {
const t = translations[e.data?.lang];
if (e.data?.type !== "sp-language" || !t) return;
document.getElementById("scroll-fade-rtl-demo").dir = t.dir;
document.querySelectorAll("[data-i18n]").forEach((el) => {
el.textContent = t[el.dataset.i18n];
});
});
</script>CSS variables
The fade reads its metrics from component-local variables. Override them per instance with an arbitrary property, or for the whole app with a plain CSS rule.
<div class="scroll-fade [--scroll-fade-reveal:8rem] h-72 overflow-y-auto">
Long content
</div>