layout
Scroll fade
Edge fades on a scroll container that hint there is more to scroll, driven by pure CSS scroll timelines.
NewCSS onlyPlain classes; no JavaScript in any stack.
Usage
The class goes on the scrolling element itself — no wrapper and no script. Each edge fades only while content hides behind it.
- Intake — Monday 09:00
- Theory lesson — Monday 11:00
- Driving lesson — Tuesday 14:00
- Driving lesson — Wednesday 09:30
- Theory exam prep — Thursday 10:00
- Driving lesson — Thursday 15:30
- Mock exam — Friday 13:00
- Driving lesson — Friday 16:00
- Intake — Saturday 10:00
- Theory lesson — Saturday 13:00
<!-- One class on the scrolling element: the end edge fades while content
hides behind it, and lifts as you reach it. -->
<ul class="ca-scroll-fade ca-scroll-fade--y h-44 w-full max-w-sm overflow-y-auto overscroll-contain" tabindex="0">
<li>Intake — Monday 09:00</li>
<li>Theory lesson — Monday 11:00</li>
<li>Driving lesson — Tuesday 14:00</li>
<li>Driving lesson — Wednesday 09:30</li>
<li>Theory exam prep — Thursday 10:00</li>
<li>Driving lesson — Thursday 15:30</li>
<li>Mock exam — Friday 13:00</li>
<li>Driving lesson — Friday 16:00</li>
<li>Intake — Saturday 10:00</li>
<li>Theory lesson — Saturday 13:00</li>
</ul>Examples
Chevron cue
Add --cue for a stronger "there is more" hint — a chevron sits at each block edge that still hides content and vanishes as that edge comes into view.
- Intake — Monday 09:00
- Theory lesson — Monday 11:00
- Driving lesson — Tuesday 14:00
- Driving lesson — Wednesday 09:30
- Theory exam prep — Thursday 10:00
- Driving lesson — Thursday 15:30
- Mock exam — Friday 13:00
- Driving lesson — Friday 16:00
- Intake — Monday 09:00
- Theory lesson — Monday 11:00
- Driving lesson — Tuesday 14:00
- Driving lesson — Wednesday 09:30
- Theory exam prep — Thursday 10:00
- Driving lesson — Thursday 15:30
- Mock exam — Friday 13:00
- Driving lesson — Friday 16:00
<!-- --cue adds a chevron at each block edge that still hides content.
Here the same list without and with the cue side by side. -->
<div class="flex w-full max-w-lg flex-wrap items-start gap-4">
<ul class="ca-scroll-fade ca-scroll-fade--y h-44 min-w-56 flex-1 overflow-y-auto overscroll-contain" tabindex="0">
<li>Intake — Monday 09:00</li>
<li>Theory lesson — Monday 11:00</li>
<li>Driving lesson — Tuesday 14:00</li>
<li>Driving lesson — Wednesday 09:30</li>
<li>Theory exam prep — Thursday 10:00</li>
<li>Driving lesson — Thursday 15:30</li>
<li>Mock exam — Friday 13:00</li>
<li>Driving lesson — Friday 16:00</li>
</ul>
<ul class="ca-scroll-fade ca-scroll-fade--y ca-scroll-fade--cue h-44 min-w-56 flex-1 overflow-y-auto overscroll-contain" tabindex="0">
<li>Intake — Monday 09:00</li>
<li>Theory lesson — Monday 11:00</li>
<li>Driving lesson — Tuesday 14:00</li>
<li>Driving lesson — Wednesday 09:30</li>
<li>Theory exam prep — Thursday 10:00</li>
<li>Driving lesson — Thursday 15:30</li>
<li>Mock exam — Friday 13:00</li>
<li>Driving lesson — Friday 16:00</li>
</ul>
</div>Axes and sizes
--x and --y limit the effect to one axis; --sm, --md and --lg set the fade depth.
- Intake — Monday 09:00
- Theory lesson — Monday 11:00
- Driving lesson — Tuesday 14:00
- Driving lesson — Wednesday 09:30
- Theory exam prep — Thursday 10:00
- Driving lesson — Thursday 15:30
- Mock exam — Friday 13:00
- Driving lesson — Friday 16:00
- Intake — Monday 09:00
- Theory lesson — Monday 11:00
- Driving lesson — Tuesday 14:00
- Driving lesson — Wednesday 09:30
- Theory exam prep — Thursday 10:00
- Driving lesson — Thursday 15:30
- Mock exam — Friday 13:00
- Driving lesson — Friday 16:00
<div class="flex w-full max-w-lg flex-wrap items-start gap-4">
<ul class="ca-scroll-fade ca-scroll-fade--y ca-scroll-fade--sm h-40 min-w-56 flex-1 overflow-y-auto overscroll-contain" tabindex="0">
<li>Intake — Monday 09:00</li>
<li>Theory lesson — Monday 11:00</li>
<li>Driving lesson — Tuesday 14:00</li>
<li>Driving lesson — Wednesday 09:30</li>
<li>Theory exam prep — Thursday 10:00</li>
<li>Driving lesson — Thursday 15:30</li>
<li>Mock exam — Friday 13:00</li>
<li>Driving lesson — Friday 16:00</li>
</ul>
<ul class="ca-scroll-fade ca-scroll-fade--y ca-scroll-fade--lg h-40 min-w-56 flex-1 overflow-y-auto overscroll-contain" tabindex="0">
<li>Intake — Monday 09:00</li>
<li>Theory lesson — Monday 11:00</li>
<li>Driving lesson — Tuesday 14:00</li>
<li>Driving lesson — Wednesday 09:30</li>
<li>Theory exam prep — Thursday 10:00</li>
<li>Driving lesson — Thursday 15:30</li>
<li>Mock exam — Friday 13:00</li>
<li>Driving lesson — Friday 16:00</li>
</ul>
</div>
<div class="ca-scroll-fade ca-scroll-fade--x mt-4 w-full max-w-lg overflow-x-auto overscroll-contain" tabindex="0">
<div class="flex w-max gap-2 pb-1">
<span class="ca-badge">Monday</span>
<span class="ca-badge">Tuesday</span>
<span class="ca-badge">Wednesday</span>
<span class="ca-badge">Thursday</span>
<span class="ca-badge">Friday</span>
<span class="ca-badge">Saturday</span>
<span class="ca-badge">Sunday</span>
<span class="ca-badge">Next week</span>
<span class="ca-badge">Exam week</span>
<span class="ca-badge">Holidays</span>
</div>
</div>Guidance and accessibility
When to use
- Use a scroll fade on any container that clips its overflow: side navigation, chat logs, pick lists, tab strips, tables. The fading edge tells the reader the content continues beyond the frame.
- Prefer
ca-scroll-fadewhen the element already scrolls natively and needs no custom scrollbars — unlikeca-scroll-area--fadeit needs no wrapper markup and no script.
How it works
- Scroll-driven animations grow each edge’s fade as content hides behind it: the end edge stays faded until you reach it, the start edge only appears once you have scrolled away.
- An axis that does not overflow shows no fade at all — its timeline stays inactive. Inline edges follow the writing direction, so RTL flips them automatically.
- Tune the depth with the size modifiers or
--ca-scroll-fade-size, and the ramp distance with--ca-scroll-fade-travel. - On low-contrast surfaces a soft fade alone may not read as scrollable.
--cuepins a chevron at each block edge that still hides content — it bobs gently and vanishes as that edge comes into view. - Browsers without scroll timelines, such as stable Firefox, show no fade. Every item stays fully readable, so the hint degrades to plain scrolling.
Accessibility
- The fade is a mask, not a clip: all items stay in the reading order and reachable by keyboard.
- Give the scroller
tabindex="0"when it contains no focusable elements, so keyboard users can scroll it.
Classes
Generated from the component contract. Parts use __, modifiers use --.
| Class | Kind | Use it for |
|---|---|---|
ca-scroll-fade | Component | Edge fades on a scroll container; each edge fades while content still hides behind it. |
ca-scroll-fade--y | Variant | Limits the fade to the block (vertical) edges. |
ca-scroll-fade--x | Variant | Limits the fade to the inline (horizontal) edges. |
ca-scroll-fade--cue | Variant | Adds a chevron cue at each block edge that still hides content; it vanishes once you reach that edge. |
ca-scroll-fade--sm | Size | A shallow fade for short lists. |
ca-scroll-fade--md | Size | The default fade depth. |
ca-scroll-fade--lg | Size | A deep fade for long scrollers. |
Skins
The same markup, dressed by each skin. Structure and behavior stay the same; only the look changes.
Base skin
Neutral grayscale starting point; product skins extend it and change what differs.
- Intake — Monday 09:00
- Theory lesson — Monday 11:00
- Driving lesson — Tuesday 14:00
- Driving lesson — Wednesday 09:30
- Theory exam prep — Thursday 10:00
- Driving lesson — Thursday 15:30
- Mock exam — Friday 13:00
- Driving lesson — Friday 16:00
- Intake — Saturday 10:00
- Theory lesson — Saturday 13:00
Calaca skin
The Calaca UI brand: hueso paper and tinta ink, cempasúchil marigold, rosa and jade.
- Intake — Monday 09:00
- Theory lesson — Monday 11:00
- Driving lesson — Tuesday 14:00
- Driving lesson — Wednesday 09:30
- Theory exam prep — Thursday 10:00
- Driving lesson — Thursday 15:30
- Mock exam — Friday 13:00
- Driving lesson — Friday 16:00
- Intake — Saturday 10:00
- Theory lesson — Saturday 13:00
Bloque skin
Example skin pushed far from base: square, heavy, offset shadows, larger targets.
- Intake — Monday 09:00
- Theory lesson — Monday 11:00
- Driving lesson — Tuesday 14:00
- Driving lesson — Wednesday 09:30
- Theory exam prep — Thursday 10:00
- Driving lesson — Thursday 15:30
- Mock exam — Friday 13:00
- Driving lesson — Friday 16:00
- Intake — Saturday 10:00
- Theory lesson — Saturday 13:00
Pliego skin
Example skin from the press sheet: cool ground, bond-paper sheets, rule-grey hairlines, one red mark.
- Intake — Monday 09:00
- Theory lesson — Monday 11:00
- Driving lesson — Tuesday 14:00
- Driving lesson — Wednesday 09:30
- Theory exam prep — Thursday 10:00
- Driving lesson — Thursday 15:30
- Mock exam — Friday 13:00
- Driving lesson — Friday 16:00
- Intake — Saturday 10:00
- Theory lesson — Saturday 13:00
Framework notes
Link the prebuilt stylesheet of your skin next to your brand stylesheet. No build step.
<link rel="stylesheet" href="brand.css" />
<link rel="stylesheet" href="ca-base.css" />In Astro, Vite and other Tailwind projects, import Calaca after Tailwind and your brand in your main stylesheet.
@import "tailwindcss";
@import "./brand.css";
@import "@usecalaca/ui/core.css";
@import "@usecalaca/ui/skins/base.css";Same stylesheet as above; write the classes in className.
<button className="ca-button ca-button--primary ca-button--md" type="button">Save changes</button>