Scroll

Move through overflowing content.

Notification settings
Privacy
Billing
Integrations
Danger zone

{{unless scrolled}}at top — scroll to see more below

html

<div class="scroll-demo" data-style="fade-edge" style="--accent:#241430;">
  <div class="scroll-demo__viewport">
    <div class="scroll-demo__list">
      <div class="scroll-demo__row">Notification settings</div>
      <div class="scroll-demo__row">Privacy</div>
      <div class="scroll-demo__row">Billing</div>
      <div class="scroll-demo__row">Integrations</div>
      <div class="scroll-demo__row">Danger zone</div>
    </div>
  </div>
  <p class="scroll-demo__caption">{{unless scrolled}}at top &mdash; scroll to see more below

tailwind

<div class="scroll-tw scroll-tw--fade-edge relative" style="width:260px;font-family:system-ui,sans-serif;color:#241430">
  <div class="h-[120px] rounded-[10px] overflow-hidden border-[1.5px]" style="border-color:#24143022">
    <div class="scroll-tw__list flex flex-col motion-safe:transition-transform">
      <div class="px-3 py-3.5 border-b bg-[#FAF7F2]" style="border-color:#24143014">Notification settings</div>
      <div class="px-3 py-3.5 border-b bg-[#FAF7F2]" style="border-color:#24143014">Privacy</div>
      <div class="px-3 py-3.5 border-b bg-[#FAF7F2]" style="border-color:#24143014">Billing</div>
      <div class="px-3 py-3.5 border-b bg-[#FAF7F2]" style="border-color:#24143014">Integrations</div>
      <div class="px-3 py-3.5 bg-[#FAF7F2]">Danger zone</div>
    </div>
  </div>
  <p class="mt-2.5 text-xs text-[#241430aa]">{{unless scrolled}}at top &mdash; scroll to see more below

react

export function ScrollDemo({
  style = "fade-edge",
  scrolled = false,
  accent = "#241430",
}) {
  const rows = ["Notification settings", "Privacy", "Billing", "Integrations", "Danger zone"];
  const viewportExtra = {
    "fade-edge": {},
    "shadow-hint": { boxShadow: "inset 0 -12px 10px -10px rgba(36,20,48,.25)" },
    "scrollbar-visible": { borderRight: "6px solid #24143022" },
  }[style];
  return (
    <div style={{ width: 260, fontFamily: "system-ui, sans-serif", fontSize: 14, color: "#241430" }}>
      <div style={{ position: "relative", height: 120, borderRadius: 10, overflow: "hidden", border: "1.5px solid #24143022", ...viewportExtra }}>
        <div className="scroll-list" style={{ display: "flex", flexDirection: "column", transform: scrolled ? "translateY(-64px)" : "none" }}>
          {rows.map((r) => <div key={r} style={{ padding: "14px 12px", borderBottom: "1px solid #24143014", background: "#FAF7F2" }}>{r}</div>)}
        </div>
        {style === "fade-edge" && <div style={{ position: "absolute", left: 0, right: 0, bottom: 0, height: 24, background: "linear-gradient(to bottom, transparent, #FAF7F2)", pointerEvents: "none" }} />}
        {style === "scrollbar-visible" && <div style={{ position: "absolute", right: -6, top: 8, width: 6, height: 40, background: accent, borderRadius: 3 }} />}
      </div>
      <p style={{ marginTop: 10, fontSize: 12, color: "#241430aa" }}>{scrolled ? "scrolled \u2014 more content is above" : "at top \u2014 scroll to see more below"}</p>
      <style>{`
        @media (prefers-reduced-motion: no-preference) {
          .scroll-list { transition: transform .2s; }
        }
      `}</style>
    </div>
  );
}