HextaUI

Scroll fade

Des bords de zone de défilement qui ne s'estompent que lorsqu'il y a plus à voir, pilotés par la position de défilement en CSS seul.

  • 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 est un ensemble d'utilitaires Tailwind issus du tailwind.css de shadcn. Le thème HextaUI l'importe déjà : si vous avez ajouté le thème ou un composant, vous l'avez.

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

Sans le thème, installez shadcn et importez son CSS après 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>

Ajoutez-le à n'importe quel élément qui défile. Un bord ne s'estompe que s'il y a encore du contenu au-delà : une rangée coupée signale « continuez à défiler » et une liste au repos garde des bords nets.

Le fondu est un mask-image : le contenu se dissout dans ce qui se trouve derrière. Il n'y a pas de dégradé en surcouche à accorder à l'arrière-plan, et cela fonctionne sur les images, les surfaces teintées et le verre. Une animation CSS pilotée par le défilement fait croître le fondu de chaque bord sur les 96 premiers et derniers px de défilement. Aucun JavaScript ne s'exécute, et rien n'est jamais re-rendu.

  • Chaque fondu fait 12% du conteneur, plafonné à 40px.
  • Les navigateurs sans animations pilotées par le défilement affichent toujours les deux fondus. C'est un peu moins précis, mais cela reste lisible comme une zone défilante.
  • scroll-fade-x, scroll-fade-s et scroll-fade-e suivent le sens d'écriture, si bien que le fondu de début se place à droite dans les mises en page de droite à gauche.

Horizontal

Une rangée de filtres qui défile latéralement. Associez-la à no-scrollbar, lui aussi issu du CSS de shadcn, quand le fondu seul montre qu'il y a plus à voir.

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>
  )
}

Un seul bord

Un chat démarre en bas, donc seuls les anciens messages au-dessus ont besoin d'un indice. scroll-fade-t n'estompe que le haut, et scroll-fade-t-16 l'allonge.

"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>

Les tailles acceptent l'échelle d'espacement ou n'importe quelle longueur ou pourcentage. --scroll-fade-reveal définit la distance à parcourir avant qu'un bord atteigne son fondu complet.

  • Le masque estompe aussi l'arrière-plan et la bordure de l'élément lui-même. Placez la surface sur un wrapper et le fondu sur l'enfant qui défile, comme dans les exemples.
  • Un masque cache tout ce qui est proche du bord, y compris les anneaux de focus. Donnez un peu de padding à l'élément qui défile pour que les éléments focalisés ne soient pas estompés.
  • Utilisez plutôt Scroll area si vous voulez aussi des barres de défilement personnalisées. Il a ses propres fondus, mesurés en JavaScript, qui fonctionnent dans tous les navigateurs.
ClasseDescription
scroll-fade, scroll-fade-yEstompe les bords haut et bas.
scroll-fade-xEstompe les bords de début et de fin, selon la direction.
scroll-fade-t, scroll-fade-bN'estompe que le bord haut ou bas.
scroll-fade-s, scroll-fade-eN'estompe que le bord de début ou de fin.
scroll-fade-l, scroll-fade-rN'estompe que le bord gauche ou droit, quelle que soit la direction.
scroll-fade-<size>Taille de chaque fondu.
scroll-fade-{t,b,s,e}-<size>Taille du fondu d'un seul bord.
scroll-fade-noneDésactive le fondu, par exemple à un point de rupture.
--scroll-fade-revealDistance de défilement sur laquelle un bord apparaît en fondu. 96px par défaut.