Scroll reveal

Reveal content once as it enters the viewport with a reduced-motion fallback.

Preview

Live preview

Elements fade or slide into place as they enter the viewport.

Preview
Scroll
Scroll reveal
Continue
Authoritative vocabulary

Definition and close-term distinctions

English definitions are preserved verbatim from Animation Vocabulary; translations and distinctions help you choose precisely.

Canonical termscroll-reveal

Scroll reveal

滚动揭示
Authoritative definition

Elements fade or slide into place as they enter the viewport.

Chinese translation

元素进入视口时淡入或滑动到位。

Browse all 91 terms
Design contract

Decide before this motion ships

Purpose, frequency, trigger, timing, interruptibility, and gesture rules shape the implementation.

Purpose

Signal a new reading section on first viewport entry while preserving scroll continuity.

Frequency

Trigger each section at most once and select only structurally meaningful nodes on long pages.

Trigger

Trigger from an IntersectionObserver threshold, showing initially visible content immediately.

Enter / exit

Enter with brief travel and fade, then remain stable after leaving the viewport.

Interruptibility

Complete the current reveal during fast scrolling to avoid animation queues.

Gesture and keyboard

Keep scrolling native and never capture wheel, touch, or keyboard scroll input for the reveal.

Reduced-motion strategy

Show content immediately on viewport entry or keep one very brief fade.

Output

Copy into your interface

Current parameters update visual-state CSS, semantic HTML, the required vanilla JS runtime, and an interaction prompt.

Updates with parameters
motion.css
.motion-demo.motion-demo--scroll-reveal {
  position: relative;
  display: grid;
  place-items: center;
  width: min(100%, 34rem);
  min-height: 15rem;
  padding: 2rem;
  overflow: hidden;
  color: #18181b;
  background: #fafafa;
  border: 1px solid #e4e4e7;
  border-radius: 12px;
  isolation: isolate;
}

.motion-demo.motion-demo--scroll-reveal *, .motion-demo.motion-demo--scroll-reveal *::before, .motion-demo.motion-demo--scroll-reveal *::after {
  box-sizing: border-box;
}

.motion-demo.motion-demo--scroll-reveal .motion-surface {
  position: relative;
  display: grid;
  gap: 0.65rem;
  width: min(100%, 18rem);
  padding: 1.25rem;
  background: #ffffff;
  border: 1px solid #e4e4e7;
  border-radius: 8px;
  box-shadow: 0 1px 2px rgb(0 0 0 / 6%), 0 10px 28px rgb(0 0 0 / 7%);
}

.motion-demo.motion-demo--scroll-reveal .motion-line {
  display: block;
  width: 100%;
  height: 0.5rem;
  background: #e4e4e7;
  border-radius: 999px;
}

.motion-demo.motion-demo--scroll-reveal .motion-line:last-child { width: 62%; }

.motion-demo.motion-demo--scroll-reveal .motion-button {
  position: relative;
  min-height: 2.75rem;
  padding: 0.75rem 1.1rem;
  color: white;
  font: inherit;
  font-weight: 700;
  background: #18181b;
  border: 0;
  border-radius: 7px;
  cursor: pointer;
}

.motion-demo.motion-demo--scroll-reveal .motion-button:focus-visible { outline: 3px solid rgb(37 99 235 / 32%); outline-offset: 3px; }

.motion-demo.motion-demo--scroll-reveal .motion-action-row {
  display: flex;
  justify-content: center;
  gap: 0.5rem;
  margin-top: 0.85rem;
}

.motion-demo.motion-demo--scroll-reveal .motion-replay-scene {
  width: min(100%, 22rem);
  display: grid;
  place-items: center;
}

.motion-demo.motion-demo--scroll-reveal .motion-pausable-scene {
  width: min(100%, 22rem);
  display: grid;
  place-items: center;
}

.motion-demo.motion-demo--scroll-reveal button.motion-surface {
  color: inherit;
  font: inherit;
  text-align: start;
  cursor: pointer;
}

.motion-demo.motion-demo--scroll-reveal .motion-replay-button,
.motion-demo.motion-demo--scroll-reveal .motion-undo-button,
.motion-demo.motion-demo--scroll-reveal .motion-dismiss-button,
.motion-demo.motion-demo--scroll-reveal .motion-pause-button {
  min-height: 2.75rem;
  padding: 0.65rem 0.9rem;
  color: #18181b;
  font: 650 0.78rem/1 ui-sans-serif, system-ui, sans-serif;
  background: #ffffff;
  border: 1px solid #d4d4d8;
  border-radius: 7px;
  cursor: pointer;
}

.motion-demo.motion-demo--scroll-reveal .motion-replay-button:focus-visible,
.motion-demo.motion-demo--scroll-reveal .motion-undo-button:focus-visible,
.motion-demo.motion-demo--scroll-reveal .motion-dismiss-button:focus-visible,
.motion-demo.motion-demo--scroll-reveal .motion-pause-button:focus-visible,
.motion-demo.motion-demo--scroll-reveal [data-reorder-item]:focus-visible,
.motion-demo.motion-demo--scroll-reveal [data-swipe-target]:focus-visible {
  outline: 3px solid rgb(37 99 235 / 32%);
  outline-offset: 3px;
}

.motion-demo.motion-demo--scroll-reveal .motion-status {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.motion-demo.motion-demo--scroll-reveal .motion-ripple-ink {
  position: absolute;
  width: 12px;
  height: 12px;
  pointer-events: none;
  background: rgb(255 255 255 / 72%);
  border-radius: 50%;
  transform: translate(-50%, -50%) scale(0.95);
  opacity: 0;
}

.motion-demo.motion-demo--scroll-reveal .motion-state-stack { position: relative; width: min(100%, 18rem); height: 9rem; }
.motion-demo.motion-demo--scroll-reveal .motion-state { position: absolute; inset: 0; display: grid; place-items: center; padding: 1rem; background: #ffffff; border: 1px solid #e4e4e7; border-radius: 8px; }
.motion-demo.motion-demo--scroll-reveal .motion-state--to { background: #18181b; color: white; }

.motion-demo.motion-demo--scroll-reveal .motion-scroll-track > span { color: #71717a; font: 600 0.72rem/1.2 ui-monospace, monospace; letter-spacing: 0.08em; text-transform: uppercase; }
.motion-demo.motion-demo--scroll-reveal .motion-orbit-item { display: grid; place-items: center; width: 2.5rem; height: 2.5rem; color: white; background: #2563eb; border-radius: 50%; }
.motion-demo.motion-demo--scroll-reveal .motion-text-stack { position: relative; width: min(100%, 18rem); min-height: 4rem; }
.motion-demo.motion-demo--scroll-reveal svg { width: min(100%, 20rem); height: auto; }

.motion-demo.motion-demo--scroll-reveal { max-height: 15rem; overflow-y: auto; place-items: start center; }
.motion-demo.motion-demo--scroll-reveal .motion-scroll-track { display: grid; place-items: center; gap: 10rem; width: 100%; min-height: 48rem; padding-block: 5rem; }
.motion-demo.motion-demo--scroll-reveal .motion-surface { animation: motion-scroll-reveal 260ms cubic-bezier(0.23, 1, 0.32, 1) both; }
@supports (animation-timeline: view()) {
  .motion-demo.motion-demo--scroll-reveal .motion-surface { animation-timeline: view(); animation-range: entry 20% cover 55%; }
}
@keyframes motion-scroll-reveal { from { opacity: 0; transform: translateY(28px); } to { opacity: 1; transform: none; } }

@keyframes motion-scroll-reveal-reduced-fade {
  from { opacity: 0.84; }
  to { opacity: 1; }
}

.force-reduced-motion .motion-demo.motion-demo--scroll-reveal {
  animation: motion-scroll-reveal-reduced-fade 160ms cubic-bezier(0.23, 1, 0.32, 1) both !important;
}

.force-reduced-motion .motion-demo.motion-demo--scroll-reveal *,
.force-reduced-motion .motion-demo.motion-demo--scroll-reveal *::before,
.force-reduced-motion .motion-demo.motion-demo--scroll-reveal *::after {
  animation: none !important;
  animation-delay: 0ms !important;
  animation-iteration-count: 1 !important;
  transition-property: opacity, color, background-color, border-color !important;
  transition-duration: 160ms !important;
  transition-delay: 0ms !important;
  scroll-behavior: auto !important;
}

.force-reduced-motion .motion-demo.motion-demo--scroll-reveal .motion-button,
.force-reduced-motion .motion-demo.motion-demo--scroll-reveal [data-reorder-item],
.force-reduced-motion .motion-demo.motion-demo--scroll-reveal [data-swipe-target],
.force-reduced-motion .motion-demo.motion-demo--scroll-reveal [data-spring-target] {
  transform: none !important;
}

.force-reduced-motion .motion-demo.motion-demo--scroll-reveal .motion-path { stroke-dashoffset: 0 !important; }
.force-reduced-motion .motion-demo.motion-demo--scroll-reveal .motion-word--from { opacity: 0 !important; visibility: hidden; }
.force-reduced-motion .motion-demo.motion-demo--scroll-reveal .motion-word:not(.motion-word--from) { opacity: 1 !important; filter: none !important; transform: none !important; }

@media (prefers-reduced-motion: reduce) {
  .motion-demo.motion-demo--scroll-reveal {
    animation: motion-scroll-reveal-reduced-fade 160ms cubic-bezier(0.23, 1, 0.32, 1) both !important;
  }

  .motion-demo.motion-demo--scroll-reveal *, .motion-demo.motion-demo--scroll-reveal *::before, .motion-demo.motion-demo--scroll-reveal *::after {
    animation: none !important;
    animation-delay: 0ms !important;
    animation-iteration-count: 1 !important;
    transition-property: opacity, color, background-color, border-color !important;
    transition-duration: 160ms !important;
    transition-delay: 0ms !important;
    scroll-behavior: auto !important;
  }

  .motion-demo.motion-demo--scroll-reveal .motion-button,
  .motion-demo.motion-demo--scroll-reveal [data-reorder-item],
  .motion-demo.motion-demo--scroll-reveal [data-swipe-target],
  .motion-demo.motion-demo--scroll-reveal [data-spring-target] {
    transform: none !important;
  }

  .motion-demo.motion-demo--scroll-reveal .motion-path { stroke-dashoffset: 0 !important; }
  .motion-demo.motion-demo--scroll-reveal .motion-word--from { opacity: 0 !important; visibility: hidden; }
  .motion-demo.motion-demo--scroll-reveal .motion-word:not(.motion-word--from) { opacity: 1 !important; filter: none !important; transform: none !important; }
}
Review notes

Pre-delivery review

  • Keep content visible when JavaScript is unavailable.
  • Do not make critical above-the-fold content wait for an observer callback.
Accessibility

Keep information accessible

Reduced motion

Show content immediately on viewport entry or keep one very brief fade.

Parameters

Parameter reference

ParameterRange / optionsDefaultPurpose
duration80ms–1200ms260msControls the time required for one motion cycle.
threshold0%–80%20%Adjusts threshold.
distance0px–120px28pxControls how far the element travels.
easeSoft / Snap / Calm / LinearSoftControls how velocity changes over time.