Skip to content

Scroll reveal

Fade-and-translate-up effect as the element enters the viewport — the canonical "scroll reveal".

Live demo

html
<div class="opacity-0 translate-y-12
            animate-fade-up animate-fill-mode-both
            timeline-view anim-range-[entry_0%_cover_25%]">
  Reveal me.
</div>
ts
import { defineConfig, presetWind3 } from 'unocss'
import presetMotion from 'unocss-preset-motion'

export default defineConfig({
  presets: [presetWind3(), presetMotion()],
  theme: {
    animation: {
      keyframes: {
        'fade-up': '{from{opacity:0;transform:translateY(3rem)}to{opacity:1;transform:translateY(0)}}',
      },
      durations: { 'fade-up': '1s' },
      timingFns: { 'fade-up': 'ease-out' },
      counts: { 'fade-up': '1' },
    },
  },
})

Scroll past the cards below to see the effect.

Reveal one

Slides up from below and fades in as it enters the viewport.

Reveal two

Each card runs its own scroll-driven animation independently.

Reveal three

No JavaScript — pure CSS animation-timeline: view().

Reveal four

Tune anim-range-[…] to shape the timing.

How it works

ClassRole
opacity-0 translate-y-12The static state — visible to users who opt out of motion.
animate-fade-upThe keyframes definition (declared in the theme).
animate-fill-mode-bothKeep the final state after the animation reaches 100%.
timeline-viewDrive the animation by the element's own viewport position, not by time.
anim-range-[entry_0%_cover_25%]Spread the animation across more scroll distance for a softer effect.

Variations

html
<!-- Punchier: animation snaps during entry only -->
<div class="… timeline-view anim-range-entry" />

<!-- Slower fade-in across the whole traversal -->
<div class="… timeline-view anim-range-cover" />

Released under the MIT License.