CSS view() Function

The CSS view() function creates an anonymous view progress timeline for a scroll-driven animation.

It tracks the visibility of an element as it moves through a scroll container's viewport, also called the scrollport. The function is used with the animation-timeline property to control animations based on an element's position rather than elapsed time.

Syntax

view()
view(<axis>)
view(<inset>)
view(<axis> <inset>)

The view() function accepts an optional axis and optional inset values.

Examples:

animation-timeline: view();
animation-timeline: view(block);
animation-timeline: view(inline);
animation-timeline: view(x);
animation-timeline: view(y);
animation-timeline: view(20%);
animation-timeline: view(20% 10%);
animation-timeline: view(block 20%);
animation-timeline: view(inline 10% 20%);

When no arguments are provided, the function uses the block axis and the default view timeline insets.

The axis and inset can appear in either order:

animation-timeline: view(block 20%);
animation-timeline: view(20% block);

Both declarations describe the same view progress timeline.

The view() function is primarily used as a value of animation-timeline.

Parameters

Parameter Description
<axis> Optional. Specifies the logical or physical scrolling axis to track.
<inset> Optional. Specifies one or two length-percentage values that adjust the view timeline's visibility boundaries.

Neither parameter is required.

For example:

.box {
  animation: reveal linear both;
  animation-timeline: view();
}

This creates a view progress timeline using the default block axis.

To specify an axis:

.box {
  animation-timeline: view(inline);
}

To adjust the visibility boundaries:

.box {
  animation-timeline: view(block 15% 25%);
}

The percentages refer to the size of the scrollport along the selected axis.

How It Works

A view progress timeline measures the movement of an element through its nearest ancestor scroll container.

The element whose visibility is tracked is called the subject of the timeline.

For example:

@keyframes reveal {
  from {
    opacity: 0;
    transform: translateY(30px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
.reveal {
  animation: reveal linear both;
  animation-timeline: view();
}

As the element moves through the scrollport, the animation progresses according to the element's position.

Unlike a conventional animation, the progress is not determined by the amount of time that has passed.

Scrolling forward advances the animation. Scrolling backward reverses its progress.

The element does not need a JavaScript scroll event listener to create this effect.

The subject must have a usable view progress timeline. Without an appropriate scroll container or scrollable range, the animation may not progress as expected.

Axis Values

The optional axis determines which direction of scrolling the timeline tracks.

Value Description
block Tracks the block axis. This is vertical in common horizontal writing modes and is the default.
inline Tracks the inline axis. This is horizontal in common horizontal writing modes.
x Tracks the physical horizontal axis.
y Tracks the physical vertical axis.

Block Axis

.box {
  animation-timeline: view(block);
}

Tracks movement along the block axis.

Inline Axis

.box {
  animation-timeline: view(inline);
}

Tracks movement along the inline axis.

Physical Axes

.horizontal {
  animation-timeline: view(x);
}
.vertical {
  animation-timeline: view(y);
}

The x and y keywords refer to physical directions, regardless of the document's writing mode.

The block and inline keywords follow the writing mode, making them useful for layouts that support different text directions.

Inset Values

Inset values adjust the boundaries used to calculate the subject's view progress.

For example:

.box {
  animation-timeline: view(block 20%);
}

The 20% inset moves both timeline visibility boundaries inward by 20% of the scrollport's size along the selected axis.

Two values can specify different insets:

.box {
  animation-timeline: view(block 10% 30%);
}

The first value applies to the start boundary, and the second applies to the end boundary along the selected axis.

Length Values

animation-timeline: view(40px);
animation-timeline: view(block 20px 60px);

Lengths adjust the visibility boundaries by fixed distances.

Percentage Values

animation-timeline: view(10%);
animation-timeline: view(block 10% 20%);

Percentages are calculated relative to the scrollport's size on the relevant axis, not the subject's size.

Negative Insets

animation-timeline: view(block -20px);

A negative inset extends the corresponding boundary outward, allowing the timeline's visibility range to extend beyond the normal scrollport boundary.

Insets affect the timeline's range rather than adding padding or changing the element's layout.

View Progress Timeline

The default view progress timeline tracks the subject as it passes through the scrollport.

Its full progress range normally begins when the subject's leading edge reaches the end edge of the adjusted scrollport and ends when the subject's trailing edge reaches the start edge.

For ordinary downward scrolling, this means the timeline can begin as the element enters from the bottom and finish after it leaves through the top.

The subject's size and the scrollport's size both affect how much scrolling is needed to complete the timeline.

For example:

.box {
  animation: fade linear both;
  animation-timeline: view();
}
@keyframes fade {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

The animation progresses as the subject moves through the view timeline's range.

The animation-fill-mode value both preserves the appropriate endpoint styles outside the active animation range.

View timelines can also expose named ranges such as entry, exit, contain, and cover.

Animation Range

The animation-range property controls which portion of the view progress timeline drives an animation.

For example:

.box {
  animation: reveal linear both;
  animation-timeline: view();
  animation-range: entry 0% entry 100%;
}

This limits the animation to the subject's entry range.

Instead of progressing through the full timeline, the animation completes as the element enters the scrollport.

Common Named Ranges

Range Description
cover The full range in which the subject passes through the adjusted scrollport.
entry The portion in which the subject enters the adjusted scrollport.
exit The portion in which the subject exits the adjusted scrollport.
contain The range associated with the subject being fully contained in the scrollport, or the scrollport being fully covered by a larger subject.
entry-crossing The range during which the subject's leading edge crosses the scrollport.
exit-crossing The range during which the subject's trailing edge crosses the scrollport.

For example, an element can fade in during entry:

.box {
  animation: fade-in linear both;
  animation-timeline: view();
  animation-range: entry;
}

Or fade out during exit:

.box {
  animation: fade-out linear both;
  animation-timeline: view();
  animation-range: exit;
}

Named ranges help create animations that respond to specific stages of an element's visibility.

view() vs. scroll()

The view() and scroll() functions both create scroll-driven animation timelines, but they track different progress measurements.

Feature view() scroll()
Progress source The subject's movement through a scrollport. A scroll container's scroll position.
Typical use Reveal effects and element-specific animations. Reading indicators and scroll progress effects.
Subject The animated element itself. A selected scroll container.
Example view(block) scroll(block)

Using view()

.box {
  animation-timeline: view();
}

The animation follows the box's movement through its scrollport.

Using scroll()

.progress-bar {
  animation-timeline: scroll();
}

The animation follows the scroll progress of the selected scroll container.

Use view() for effects tied to an individual element's visibility and scroll() for effects tied to scrolling through a container.

Example

The following example animates boxes as they move into a vertically scrolling container.

HTML:

<div class="view-demo">
  <div class="view-box">HTML</div>
  <div class="view-box">CSS</div>
  <div class="view-box">JavaScript</div>
  <div class="view-box">Web Design</div>
</div>

CSS:

.view-demo {
  height: 240px;
  padding: 20px;
  overflow-y: auto;
  background-color: #f1f3f5;
}
.view-box {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 110px;
  margin-bottom: 70px;
  color: #fff;
  background-color: #3498db;
}
@keyframes view-reveal {
  from {
    opacity: 0;
    transform: translateY(30px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
@supports (animation-timeline: view()) {
  .view-box {
    animation: view-reveal linear both;
    animation-timeline: view();
    animation-range: entry 0% entry 100%;
  }
}
@media (prefers-reduced-motion: reduce) {
  .view-box {
    animation: none;
  }
}
Browser Result
HTML
CSS
JavaScript
Web Design

Scroll inside the example to move the boxes through the container.

In supporting browsers, each box fades in and moves upward as it enters the scrollport.

Browsers without view timeline support display the boxes without the animation.

The reduced-motion media query disables the animation for users who request reduced motion.

Horizontal Scrolling Example

The following example uses view(inline) to track elements moving through a horizontally scrolling container.

HTML:

<div class="view-horizontal-demo">
  <div class="view-horizontal-box">One</div>
  <div class="view-horizontal-box">Two</div>
  <div class="view-horizontal-box">Three</div>
  <div class="view-horizontal-box">Four</div>
</div>

CSS:

.view-horizontal-demo {
  display: flex;
  gap: 80px;
  overflow-x: auto;
  padding: 25px;
  background-color: #f1f3f5;
}
.view-horizontal-box {
  display: flex;
  flex: 0 0 160px;
  align-items: center;
  justify-content: center;
  height: 110px;
  color: #fff;
  background-color: #16a085;
}
@keyframes view-horizontal-reveal {
  from {
    opacity: 0;
    transform: scale(0.7);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}
@supports (animation-timeline: view(inline)) {
  .view-horizontal-box {
    animation: view-horizontal-reveal linear both;
    animation-timeline: view(inline);
    animation-range: entry;
  }
}
@media (prefers-reduced-motion: reduce) {
  .view-horizontal-box {
    animation: none;
  }
}
Browser Result
One
Two
Three
Four

Scroll horizontally to bring additional boxes into view.

The inline axis follows horizontal scrolling in the normal horizontal writing mode.

Each box grows from a smaller size as it enters the visible area in supporting browsers.

Inset Example

The following example uses view(block 20%) to adjust the boundaries of a vertical view progress timeline.

HTML:

<div class="view-inset-demo">
  <div class="view-inset-box">First</div>
  <div class="view-inset-box">Second</div>
  <div class="view-inset-box">Third</div>
  <div class="view-inset-box">Fourth</div>
</div>

CSS:

.view-inset-demo {
  height: 240px;
  padding: 20px;
  overflow-y: auto;
  background-color: #f1f3f5;
}
.view-inset-box {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100px;
  margin-bottom: 90px;
  color: #fff;
  background-color: #8e44ad;
}
@keyframes view-inset-fade {
  from {
    opacity: 0.2;
  }
  to {
    opacity: 1;
  }
}
@supports (animation-timeline: view(block 20%)) {
  .view-inset-box {
    animation: view-inset-fade linear both;
    animation-timeline: view(block 20%);
    animation-range: entry;
  }
}
@media (prefers-reduced-motion: reduce) {
  .view-inset-box {
    animation: none;
  }
}
Browser Result
First
Second
Third
Fourth

Scroll inside the container to see how the boxes respond.

The 20% inset moves the view timeline's boundaries inward, changing the portion of the scrollport used to calculate entry progress.

This allows the animation to respond to a narrower visibility region without changing the container's padding or layout.

Common Uses

The view() function is useful for animations based on an element's visibility within a scrolling area.

  • Reveal animations: Fade or slide elements into view as the user scrolls.
  • Image effects: Change opacity, scale, or position as images enter the scrollport.
  • Content sections: Animate cards, headings, and other page components during scrolling.
  • Horizontal galleries: Animate items as they enter a horizontally scrolling container.
  • Custom visibility ranges: Use inset values to adjust when animations progress.
  • Entry and exit effects: Use animation-range to target specific visibility stages.
  • Scroll-driven interfaces: Connect visual changes directly to scrolling without JavaScript scroll event handlers.

For example:

.section-heading {
  animation: heading-reveal linear both;
  animation-timeline: view();
  animation-range: entry;
}
@keyframes heading-reveal {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

The heading animates as it enters the scrollport in supporting browsers.

For essential content, ensure the page remains readable when scroll-driven animations are unavailable or disabled.

Limitations

The view() function has several requirements and behaviors to consider.

  • It is part of CSS scroll-driven animations and has limited availability across browsers.
  • It is used with properties that accept animation timelines, primarily animation-timeline.
  • The timeline tracks the animated element as the subject of the view timeline.
  • The element needs a suitable ancestor scroll container and a usable scrolling range.
  • The selected axis must correspond to the intended scrolling direction.
  • Inset values adjust timeline boundaries but do not change layout or scrolling behavior.
  • Scroll-driven animations depend on scroll position rather than elapsed time.
  • The animation-duration property does not determine how long scrolling takes.
  • Unsupported browsers may ignore the timeline declaration.
  • Users requesting reduced motion should receive a suitable non-animated presentation.

Valid Examples

animation-timeline: view();
animation-timeline: view(block);
animation-timeline: view(inline);
animation-timeline: view(x);
animation-timeline: view(y);
animation-timeline: view(20%);
animation-timeline: view(block 10% 20%);
animation-timeline: view(30px inline);

Invalid Examples

animation-timeline: view(horizontal);
animation-timeline: view(block inline);
animation-timeline: view(10% 20% 30px);
animation-timeline: view(block block);

The first example uses an unsupported axis keyword.

The second and fourth examples specify more than one axis.

The third example supplies more than two inset values.

Animation Shorthand Order

The animation shorthand resets animation-timeline to its initial value.

For example, this order is incorrect:

.box {
  animation-timeline: view();
  animation: reveal linear both;
}

The later shorthand resets the previously specified timeline.

Instead, declare animation-timeline after the shorthand:

.box {
  animation: reveal linear both;
  animation-timeline: view();
}

This ensures that the intended view progress timeline is applied.

Reduced Motion

Scroll-driven effects can still create motion that some users find distracting.

@media (prefers-reduced-motion: reduce) {
  .box {
    animation: none;
  }
}

Disabling the animation allows the element to remain visible without the scroll-driven effect.

Browser Support

The CSS view() function has Limited availability and is not Baseline Widely available across major browsers.

Support depends on the browser's implementation of CSS scroll-driven animations, including anonymous view progress timelines and the animation-timeline property.

Some browsers may require experimental settings or may not support all related features.

For current compatibility information, visit Can I Use? and search for scroll-driven animations.

Provide fallback styling and test the animation in the browsers you intend to support.

Specifications

The view() function is defined in the Scroll-driven Animations Module Level 1 specification.

The specification defines scroll progress timelines, view progress timelines, anonymous timeline functions, and named animation ranges.

Related features include scroll(), animation-timeline, animation-range, view-timeline, and CSS keyframe animations.