Command Palette
Search for a command to run...
Loading component...
Scroll with fade effect
A top/bottom scrollable fade effect that creates smooth visual transitions at the top and bottom edges. And the best part is it doesn't use any JS or functions, just simple pure CSS animation.
Dependencies
Interaction Type
| Scroll to see the fade effect | |
| Watch the smooth fade transitions | |
| Lightweight css only animation |
npx shadcn add @skiper-ui/skiper87Under the hood
It's a simple animation timeline using CSS. The CSS class below is by Gustav Ekerot and slightly tweaked by me.
Update global.css
/* Scroll Fade Effect */ @supports (animation-timeline: scroll()) { @property --ft { syntax: "<length>"; inherits: false; initial-value: 0px; } @property --fb { syntax: "<length>"; inherits: false; initial-value: 40px; } .scroll-fade-y, [data-slot="scroll-area-viewport"] { --ft: 0px; --fb: 40px; mask-image: linear-gradient( to bottom, transparent 0, #000 var(--ft), #000 calc(100% - var(--fb)), transparent 100% ); mask-size: 100% 100%; mask-repeat: no-repeat; animation: fadeTop 1 linear both, fadeBottom 1 linear both; animation-timeline: scroll(self), scroll(self); animation-range: 0% 12%, 88% 100%; } @keyframes fadeTop { from { --ft: 0px; } to { --ft: 40px; } } @keyframes fadeBottom { from { --fb: 40px; } to { --fb: 0px; } } }
How to implement
import React from "react"; const Skiper87 = () => { return ( <div className="rounded-xl border"> <div className="scroll-fade-y w-62 h-72 overflow-scroll rounded-xl"> <div className="space-y-1 p-1"> {Array.from({ length: 11 }).map((_, index) => ( <div key={index} className="text-foreground/30 bg-foreground/5 flex h-10 w-full items-center gap-2 rounded-lg px-4" > 00{index} <div className="bg-foreground/10 h-px flex-1"></div> </div> ))} </div> </div> </div> ); }; export { Skiper87 };
How to implement with scroll area
<div className="rounded-xl border"> <ScrollArea className="w-62 h-72 rounded-xl"> <div className="space-y-1 p-1"> {Array.from({ length: 11 }).map((_, index) => ( <div key={index} className="text-foreground/30 hover:bg-foreground/10 bg-foreground/5 flex h-10 w-full items-center gap-2 rounded-lg px-4" > 00{index} <div className="bg-foreground/10 h-px flex-1"></div> </div> ))} </div> </ScrollArea> </div>
But wait, we didn't add the fade class here - how come it's working? In our global CSS, we added [data-slot="scroll-area-viewport"] in global.css which automatically applies the fade effect to the ScrollArea component. Alternatively, you can update the ScrollArea viewport and add the scroll-fade-y class there.
Attribution
- Built on top of shadcn/ui ScrollArea component
- OG jh3yy's post on scroll masking.
- Recreated by Gustav Ekerot
- Recreated by me Gur__vi
Source code
Keep in mind
Most components here are recreations of the best out there. I don't claim to be the original creator. This is my attempt to reverse-engineer, replicate, and often add a few extra features. I've tried to credit everyone, but if I missed something, let me know.
Contact
License & Usage:
- Free to use and modify in both personal and commercial projects.
- Attribution to Skiper UI is required when using the free version.
- No attribution required with Skiper UI Pro.