CSS ::view-transition-group() Pseudo-Element

The ::view-transition-group() pseudo-element represents an individual snapshot group during a View Transition. It controls how a participating element's visual representation changes in size and position between the old and new document states, and allows developers to customize the animation of each transition group.

Syntax

::view-transition-group(name) {
  property: value;
}

The name argument identifies the View Transition group to style.

The name normally corresponds to a value assigned using the view-transition-name property.

For example:

::view-transition-group(root) {
  animation-duration: 500ms;
}

This sets the animation duration for the root transition group.

To target a custom group:

::view-transition-group(featured-card) {
  animation-duration: 400ms;
}

This targets the group named featured-card.

To target every View Transition group:

::view-transition-group(*) {
  animation-duration: 300ms;
}

The universal selector * matches all generated transition groups.

The parentheses are required because ::view-transition-group() is a functional pseudo-element.

How It Works

When a View Transition begins, the browser captures the visual states of participating elements before and after the document changes.

Each element with a distinct view-transition-name can receive its own transition group.

The browser generates a ::view-transition-group() pseudo-element to contain that group's old and new visual representations.

The process generally follows these steps:

  1. A View Transition starts through JavaScript or an eligible document navigation.
  2. The browser captures the old visual state of participating elements.
  3. The document changes to its new state.
  4. The browser captures the new visual state and generates the transition groups.
  5. Each group animates between its old and new size and position when both states exist.
  6. The temporary transition pseudo-elements are removed when the transition finishes.

For example, a card might move from the left side of a container to the right side.

If the card has a unique transition name in both states, the browser can match the two visual representations.

The corresponding ::view-transition-group() animates the card's position and dimensions.

The old and new images inside that group can also be animated independently.

The pseudo-element exists only during an active View Transition.

View Transition Pseudo-Element Tree

The browser creates a temporary hierarchy of pseudo-elements for each View Transition.

A simplified tree for the root transition looks like this:

::view-transition
  ::view-transition-group(root)
    ::view-transition-image-pair(root)
      ::view-transition-old(root)
      ::view-transition-new(root)

Each pseudo-element has a specific responsibility.

Pseudo-Element Purpose
::view-transition Contains all View Transition groups in the overlay.
::view-transition-group() Controls the size, position, and animation of an individual group.
::view-transition-image-pair() Contains the old and new visual representations for a group.
::view-transition-old() Represents the old visual state.
::view-transition-new() Represents the new visual state.

When multiple elements have different transition names, the browser can create multiple groups.

For example:

::view-transition
  ::view-transition-group(root)
  ::view-transition-group(header)
  ::view-transition-group(featured-card)

Each group has its own image pair containing the applicable old and new representations.

This allows different parts of a page to animate independently.

Understanding Group Names

The view-transition-name property assigns an identifying name to an element that participates in a View Transition.

For example:

.featured-card {
  view-transition-name: featured-card;
}

The browser can then generate a group with that name:

::view-transition-group(featured-card) {
  animation-duration: 500ms;
}

The name inside ::view-transition-group() must match the assigned transition name.

Different elements can use different names:

.site-logo {
  view-transition-name: site-logo;
}
.featured-card {
  view-transition-name: featured-card;
}

Their groups can be styled separately:

::view-transition-group(site-logo) {
  animation-duration: 250ms;
}
::view-transition-group(featured-card) {
  animation-duration: 600ms;
}

The logo uses a shorter transition, while the card uses a longer one.

Each rendered participating element must have a unique transition name within a document state.

Assigning the same name to multiple rendered elements at the same time can cause the transition to be skipped.

By default, the document's root element uses the transition name root.

The name root is not required for custom elements, but it is commonly used when styling the default whole-document transition.

Selecting All Transition Groups

The universal selector * can be used inside ::view-transition-group() to target all generated groups.

For example:

::view-transition-group(*) {
  animation-duration: 400ms;
}

This sets a common animation duration for every transition group.

A named group can override that duration:

::view-transition-group(*) {
  animation-duration: 400ms;
}
::view-transition-group(featured-card) {
  animation-duration: 700ms;
}

The named card group uses 700 milliseconds, while the other groups use 400 milliseconds.

This approach is useful when most elements should share a consistent animation speed, but selected elements need special treatment.

The universal selector matches View Transition groups, not every HTML element in the document.

Controlling Animation Duration

One of the most common uses of ::view-transition-group() is controlling animation duration.

For example:

::view-transition-group(root) {
  animation-duration: 500ms;
}

This changes the duration of the root transition group's animation.

Animation-related properties can inherit from the group to its nested transition pseudo-elements.

Setting a common duration on the group helps keep the group movement and its old and new visual representations synchronized.

For example:

::view-transition-group(featured-card) {
  animation-duration: 600ms;
  animation-timing-function: ease-in-out;
}

This requests a 600-millisecond transition with easing for the named card group.

To apply different durations to different groups:

::view-transition-group(header) {
  animation-duration: 250ms;
}
::view-transition-group(content) {
  animation-duration: 450ms;
}

The header and content groups can animate at different speeds.

If a nested pseudo-element has its own explicit animation settings, those declarations can override inherited values.

Animating Size and Position

The ::view-transition-group() pseudo-element is responsible for the movement and resizing of a participating visual group.

When an element changes position, the browser can animate the group's transform between the old and new screen positions.

When an element changes dimensions, the browser can animate the group's width and height.

For example:

.moving-card {
  view-transition-name: moving-card;
  width: 120px;
}
.layout-changed .moving-card {
  width: 220px;
  margin-left: auto;
}

When the class changes during a View Transition, the card becomes wider and moves toward the right side of its container.

The browser can animate the matching transition group between those states.

The group animation duration can be customized:

::view-transition-group(moving-card) {
  animation-duration: 700ms;
  animation-timing-function: ease-in-out;
}

There is usually no need to manually animate the group's width, height, or transform.

The browser generates the appropriate animations from the captured old and new geometry.

Custom positioning and transform rules should be used carefully because they can interfere with that automatic behavior.

Example

The following example demonstrates a named View Transition group that moves and resizes a card.

Click the button to move the card to the opposite side of its container and change its width.

HTML:

<div class="vt-group-demo" id="vt-group-demo">
  <div class="vt-group-track">
    <div class="vt-group-card">CSS View Transition</div>
  </div>
  <button type="button" id="vt-group-toggle">Move Card</button>
</div>

CSS:

.vt-group-demo {
  max-width: 300px;
}
.vt-group-track {
  display: flex;
  align-items: center;
  min-height: 110px;
  padding: 10px;
  border: 1px solid #ccc;
  background-color: #f5f5f5;
}
.vt-group-card {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 130px;
  min-height: 70px;
  padding: 10px;
  box-sizing: border-box;
  border-radius: 6px;
  background-color: #0066cc;
  color: #fff;
  font-weight: bold;
  text-align: center;
  view-transition-name: group-demo-card;
}
.vt-group-demo.is-moved .vt-group-card {
  width: 190px;
  margin-left: auto;
  border-radius: 18px;
  background-color: #333;
}
.vt-group-demo button {
  margin-top: 12px;
  padding: 8px 14px;
  border: 0;
  background-color: #0066cc;
  color: #fff;
  cursor: pointer;
}
::view-transition-group(group-demo-card) {
  animation-duration: 700ms;
  animation-timing-function: ease-in-out;
}

JavaScript:

const demo = document.querySelector("#vt-group-demo");
const button = document.querySelector("#vt-group-toggle");
button.addEventListener("click", () => {
  const update = () => demo.classList.toggle("is-moved");
  const reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
  if (document.startViewTransition && !reduceMotion) {
    document.startViewTransition(update);
  } else {
    update();
  }
});
Browser Result
CSS View Transition

Try it: Click Move Card to move and resize the card. Click again to return it to its original position.

In supporting browsers, the card animates between the two positions and sizes.

The view-transition-name property identifies the card as group-demo-card.

The ::view-transition-group(group-demo-card) rule controls the duration and easing of the generated group animation.

The browser automatically calculates the old and new geometry.

If View Transitions are unsupported or reduced motion is preferred, the card changes immediately without the transition animation.

Note: The named card is animated independently of the rest of the page. The example uses a unique transition name to avoid conflicts with other components.

Using View Transition Classes

The view-transition-class property provides an additional way to style multiple transition groups using a shared identifier.

Unlike view-transition-name, a transition class does not need to be unique.

For example:

.card-one {
  view-transition-name: card-one;
  view-transition-class: cards;
}
.card-two {
  view-transition-name: card-two;
  view-transition-class: cards;
}

Each card has its own unique transition name, but both share the transition class cards.

The groups can be styled together:

::view-transition-group(.cards) {
  animation-duration: 500ms;
}

The dot before cards identifies a View Transition class selector.

A named group can still receive its own styling:

::view-transition-group(card-one) {
  animation-duration: 700ms;
}

This approach is useful when several independently animated elements should share common transition styling.

The view-transition-class property does not create a transition group by itself. The participating elements still need appropriate transition names.

Check browser support when using View Transition classes because their availability may differ from basic View Transition support.

::view-transition-group() vs. ::view-transition-image-pair()

The ::view-transition-group() and ::view-transition-image-pair() pseudo-elements are closely related but have different responsibilities.

Feature ::view-transition-group() ::view-transition-image-pair()
Purpose Contains and positions an individual transition group. Contains the group's old and new visual representations.
Hierarchy Child of ::view-transition. Child of ::view-transition-group().
Common styling Animation duration, position, size, and transforms. Blending, isolation, and presentation of the image pair.
Example ::view-transition-group(card) ::view-transition-image-pair(card)

For example:

::view-transition-group(card) {
  animation-duration: 500ms;
}
::view-transition-image-pair(card) {
  isolation: isolate;
}

The first rule controls the group's animation duration.

The second rule controls how the old and new representations are isolated for compositing.

Use ::view-transition-group() for the movement and dimensions of a participating element.

Use ::view-transition-image-pair() when customizing the container holding the old and new visual representations.

Supported CSS Properties

The ::view-transition-group() pseudo-element is a generated box that supports applicable CSS animation, layout, and visual styling properties.

The browser also generates styles that animate its geometry during the transition.

Property Purpose
animation-duration Controls how long the group animation takes.
animation-timing-function Controls the animation's acceleration and easing.
animation-delay Delays an animation when applicable.
animation-fill-mode Controls animation styles before and after playback.
transform Controls transforms, including generated movement animations.
transform-origin Controls the origin used for transforms.
width and height Control dimensions, which the browser can animate between states.
position Controls positioning of the generated group box.
opacity Controls group transparency.
filter Applies visual effects to the group.

For example:

::view-transition-group(featured-card) {
  animation-duration: 600ms;
  animation-timing-function: ease-in-out;
  transform-origin: center;
}

This customizes the duration, easing, and transform origin of the named group.

Because the browser generates size and position animations automatically, overriding those properties can produce unexpected results.

For ordinary View Transitions, adjusting animation duration and easing is usually sufficient.

Limitations

The ::view-transition-group() pseudo-element has several limitations.

  • It exists only while a View Transition is active.
  • It does not start a View Transition by itself.
  • It only represents groups created for participating transition names.
  • It does not permanently change the underlying HTML element's position or dimensions.
  • Each participating element must have a unique transition name within a document state.
  • Custom transforms or positioning can interfere with browser-generated movement animations.
  • Animations may be skipped when a transition is interrupted or its requirements are not satisfied.
  • Support for advanced features such as View Transition classes may differ from basic group support.
  • Cross-document transitions have additional navigation and browser requirements.

For example, this rule does not create a group:

::view-transition-group(featured-card) {
  animation-duration: 500ms;
}

The browser must first generate a group named featured-card during an active transition.

Use the view-transition-name property and an appropriate transition mechanism to create the necessary conditions.

Accessibility Considerations

Animating the size and position of page elements can improve visual continuity, but excessive movement can be distracting or uncomfortable.

Follow these accessibility practices:

  • Respect the user's reduced-motion preference.
  • Avoid rapid, repetitive, or unnecessary movement.
  • Keep animations short and predictable.
  • Ensure content remains usable without animation.
  • Preserve logical keyboard focus during document updates.
  • Do not use movement alone to communicate essential information.
  • Avoid animations that obscure important controls or text.
  • Test transitions at different zoom levels and viewport sizes.

For example, reduce the duration of all transition groups when reduced motion is preferred:

@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) {
    animation-duration: 0.01ms;
  }
}

This minimizes the duration of the generated animations.

For same-document transitions, JavaScript can also skip the View Transition entirely:

const reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
if (document.startViewTransition && !reduceMotion) {
  document.startViewTransition(updatePage);
} else {
  updatePage();
}

This performs the update immediately when reduced motion is preferred or the API is unavailable.

Browser Support

The ::view-transition-group() pseudo-element has a Baseline Newly available status, with support across the latest major browsers since October 2025.

It is supported in current versions of Chrome, Edge, Firefox, Safari, and other browsers implementing CSS View Transitions.

Older browser versions may not support the feature.

Same-document and cross-document View Transitions have separate compatibility requirements.

To check whether the selector is recognized:

@supports selector(::view-transition-group(root)) {
  ::view-transition-group(root) {
    animation-duration: 500ms;
  }
}

This applies the styling only when the browser recognizes the selector.

It does not start a transition or guarantee that a matching group will be generated.

For same-document transitions, provide a fallback when the JavaScript API is unavailable:

if (document.startViewTransition) {
  document.startViewTransition(updatePage);
} else {
  updatePage();
}

For current compatibility information, visit Can I Use? and search for View Transitions API.

Check advanced features such as View Transition classes separately when using them in production.

Specifications

The ::view-transition-group() pseudo-element is defined in the CSS View Transitions Module Level 1 .

The specification defines the generated group pseudo-elements and their role in animating the position and dimensions of participating elements.

Related features include ::view-transition, ::view-transition-image-pair(), ::view-transition-old(), ::view-transition-new(), the view-transition-name property, and the View Transitions API.