10.3k

scroll-fade

PreviousNext

Scroll-aware edge-fade utilities that fade the edges of a scroll container as it overflows.

Item 1
Item 2
Item 3
Item 4
Item 5
Item 6
Item 7
Item 8
Item 9
Item 10
Item 11
Item 12
<script setup lang="ts">
const items = Array.from({ length: 12 }, (_, index) => `Item ${index + 1}`)
</script>

<template>
  <div class="mx-auto w-full max-w-xs overflow-hidden rounded-2xl border">
    <div class="scroll-fade scrollbar-none h-72 overflow-y-auto">
      <div class="flex flex-col gap-1.5 p-1.5">
        <div
          v-for="item in items"
          :key="item"
          class="rounded-lg bg-muted px-3 py-2.5 text-sm"
        >
          {{ item }}
        </div>
      </div>
    </div>
  </div>
</template>

Installation

If your project was set up with npx shadcn-vue@latest init, you already have scroll-fade. It ships with the shadcn-vue package, which the CLI imports in your global CSS file.

Usage

Add a fade to any scroll container. The fade is driven by CSS scroll-driven animations, so an edge only fades while there is content to reveal in that direction — no JavaScript required.

<template>
  <div class="scroll-fade h-72 overflow-y-auto">
    <!-- long content -->
  </div>
</template>
ClassStyles
scroll-fadeFades the top and bottom edges (alias: scroll-fade-y).
scroll-fade-xFades the start and end edges (logical, RTL-aware).
scroll-fade-tFades the top edge only.
scroll-fade-bFades the bottom edge only.
scroll-fade-sFades the start edge only (logical, RTL-aware).
scroll-fade-eFades the end edge only (logical, RTL-aware).
scroll-fade-lFades the left edge only (physical).
scroll-fade-rFades the right edge only (physical).
scroll-fade-noneRemoves the fade mask (e.g. to disable it responsively).

The effect is pure CSS. The container is painted with a mask-image gradient whose transparent stops animate to 0 as the corresponding edge reaches the end of its scroll range. Where scroll-driven animations are unsupported, it falls back to a static fade.

Size

Set the fade length with scroll-fade-<number> (spacing scale) or an arbitrary value. The default is min(12%, 2.5rem).

<template>
  <!-- 8 * 0.25rem = 2rem fade -->
  <div class="scroll-fade scroll-fade-8 overflow-y-auto">
    <!-- long content -->
  </div>
</template>

Per-edge sizes are available too: scroll-fade-t-<number>, scroll-fade-b-<number>, scroll-fade-s-<number>, scroll-fade-e-<number>.