HextaUI

Scroll fade

Ränder eines Scrollbereichs, die nur ausblenden, wenn es mehr zu sehen gibt, allein über die Scrollposition in CSS gesteuert.

  • v2.24.0Released
  • v2.23.0Released
  • v2.22.0Released
  • v2.21.0Released
  • v2.20.0Released
  • v2.19.0Released
  • v2.18.0Released
  • v2.17.0Released
  • v2.16.0Released
  • v2.15.0Released
  • v2.14.0Released
  • v2.13.0Released
  • v2.12.0Released
  • v2.11.0Released
  • v2.10.0Released
  • v2.9.0Released
  • v2.8.0Released
  • v2.7.0Released
  • v2.6.0Released
  • v2.5.0Released
  • v2.4.0Released
  • v2.3.0Released
  • v2.2.0Released
  • v2.1.0Released
const releases = Array.from({ length: 24 }, (_, index) => `v2.${24 - index}.0`)

export function ScrollFadeDemo() {
  return (
    <div className="w-full max-w-xs rounded-xl bg-muted">
      <ul
        tabIndex={0}
        aria-label="Releases"
        className="h-64 scroll-fade overflow-y-auto rounded-xl p-2 text-sm outline-none focus-visible:ring-3 focus-visible:ring-focus-ring focus-visible:outline-hidden"
      >
        {releases.map((release) => (
          <li
            key={release}
            className="flex h-9 items-center justify-between rounded-md px-3"
          >
            <span className="font-mono">{release}</span>
            <span className="text-muted-foreground">Released</span>
          </li>
        ))}
      </ul>
    </div>
  )
}

Scroll fade ist eine Reihe von Tailwind-Utilities aus dem tailwind.css von shadcn. Das HextaUI-Theme importiert es bereits, wenn du also das Theme oder eine Komponente hinzugefügt hast, hast du es.

pnpm dlx shadcn@latest add https://hextaui.com/r/theme.json

Ohne das Theme installiere shadcn und importiere sein CSS nach Tailwind.

pnpm add shadcn
app/globals.css
@import "tailwindcss";
@import "shadcn/tailwind.css";
<div className="scroll-fade h-64 overflow-y-auto">…</div>
<div className="flex scroll-fade-x overflow-x-auto">…</div>

Füge es jedem scrollenden Element hinzu. Ein Rand blendet nur aus, solange dahinter mehr Inhalt liegt, sodass eine abgeschnittene Zeile „weiterscrollen“ signalisiert und eine ruhende Liste scharfe Ränder behält.

Der Fade ist ein mask-image, sodass sich der Inhalt in das auflöst, was dahinter liegt. Es gibt keinen Überlagerungsverlauf, der an den Hintergrund angepasst werden muss, und es funktioniert auf Bildern, getönten Flächen und Glas. Eine CSS-scrollgesteuerte Animation lässt den Fade jedes Rands über die ersten und letzten 96px des Scrollens wachsen. Es läuft kein JavaScript, und es rendert nie neu.

  • Jeder Fade ist 12% des Containers, bei höchstens 40px.
  • Browser ohne scrollgesteuerte Animationen zeigen beide Fades dauerhaft. Das ist etwas ungenauer, wirkt aber weiterhin scrollbar.
  • scroll-fade-x, scroll-fade-s und scroll-fade-e folgen der Schreibrichtung, sodass der Start-Fade in rechts-nach-links-Layouts rechts sitzt.

Horizontal

Eine Reihe von Filtern, die seitlich scrollt. Kombiniere sie mit no-scrollbar, ebenfalls aus dem CSS von shadcn, wenn der Fade allein zeigt, dass es mehr gibt.

const topics = [
  "All",
  "Design",
  "Engineering",
  "Product",
  "Research",
  "Marketing",
  "Sales",
  "Support",
  "Operations",
  "Finance",
]

export function ScrollFadeHorizontal() {
  return (
    <div
      tabIndex={0}
      role="region"
      aria-label="Topics"
      className="no-scrollbar flex w-full max-w-sm scroll-fade-x gap-2 overflow-x-auto rounded-md outline-none focus-visible:ring-3 focus-visible:ring-focus-ring focus-visible:outline-hidden"
    >
      {topics.map((topic) => (
        <span
          key={topic}
          className="shrink-0 rounded-full bg-muted px-3 py-1.5 text-sm"
        >
          {topic}
        </span>
      ))}
    </div>
  )
}

Ein Rand

Ein Chat beginnt unten, sodass nur ältere Nachrichten darüber einen Hinweis brauchen. scroll-fade-t blendet nur oben aus, und scroll-fade-t-16 macht es höher.

"use client"

const messages = Array.from({ length: 16 }, (_, index) => ({
  id: index,
  text: index % 3 === 0 ? "Sounds good, ship it." : "Pushed the fix to main.",
}))

export function ScrollFadeEdge() {
  return (
    <div className="w-full max-w-xs rounded-xl bg-muted">
      <ul
        ref={(node) => {
          if (node) {
            node.scrollTop = node.scrollHeight
          }
        }}
        tabIndex={0}
        aria-label="Messages"
        className="flex h-64 scroll-fade-t flex-col gap-2 overflow-y-auto rounded-xl p-3 text-sm outline-none scroll-fade-t-16 focus-visible:ring-3 focus-visible:ring-focus-ring focus-visible:outline-hidden"
      >
        {messages.map((message) => (
          <li
            key={message.id}
            className="w-fit max-w-[80%] shrink-0 rounded-2xl bg-background px-3 py-2 even:self-end even:bg-primary even:text-primary-foreground"
          >
            {message.text}
          </li>
        ))}
      </ul>
    </div>
  )
}
<div className="scroll-fade scroll-fade-16 overflow-y-auto">…</div>
<div className="scroll-fade scroll-fade-[20%] overflow-y-auto">…</div>
<div className="scroll-fade [--scroll-fade-reveal:12rem] overflow-y-auto">…</div>

Größen nehmen die Spacing-Skala oder eine beliebige Länge oder Prozentangabe. --scroll-fade-reveal legt fest, wie weit du scrollst, bevor ein Rand seinen vollen Fade erreicht.

  • Die Maske blendet auch den eigenen Hintergrund und Rahmen des Elements aus. Setze die Fläche auf einen Wrapper und den Fade auf das scrollende Kind, wie es die Beispiele tun.
  • Eine Maske verbirgt alles am Rand, auch Fokusringe. Gib dem scrollenden Element etwas Padding, damit fokussierte Items nicht ausgeblendet werden.
  • Nutze stattdessen Scroll area, wenn du auch eigene Scrollleisten willst. Sie hat eigene Fades, per JavaScript gemessen, die in jedem Browser funktionieren.
KlasseBeschreibung
scroll-fade, scroll-fade-yBlendet den oberen und unteren Rand aus.
scroll-fade-xBlendet den Start- und Endrand aus, der Richtung folgend.
scroll-fade-t, scroll-fade-bBlendet nur den oberen oder unteren Rand aus.
scroll-fade-s, scroll-fade-eBlendet nur den Start- oder Endrand aus.
scroll-fade-l, scroll-fade-rBlendet nur den linken oder rechten Rand aus, unabhängig von der Richtung.
scroll-fade-<size>Größe aller Fades.
scroll-fade-{t,b,s,e}-<size>Größe des Fades eines Rands.
scroll-fade-noneSchaltet den Fade ab, zum Beispiel bei einem Breakpoint.
--scroll-fade-revealScrollstrecke, über die ein Rand einblendet. Standard ist 96px.