@view-transition - At-rule CSS

@view-transition

Summary of characteristics of the @view-transition at-rule

Quick description
Enables or disables view transitions between pages.
Status
Standard
Usable for
HTML
W3C Module
CSS View Transitions Module
References (W3C)
Document status: WD (Working Draft)

Description of the @view-transition at-rule.

The @view-transition at-rule enables Cross-Document View Transitions. When pages include this directive in their styles, the passage from one page to another is done with an animation: fade effect, scrolling, etc.

Careful! Both pages must be from the same domain.

An example of what can be achieved can be seen by clicking on the links below. But several browsers do not yet support this technology. First, click on the test link to find out if the browser that you're using supports display transitions: Test Link - Demo link.

Note: The @view-transition directive can be included in the @media conditional directive. This allows you to activate the transitions only if the terminal's capacities are sufficient. There is no need to test browser compatibility: if the browser is not compatible transitions are simply not executed, but the transition from one page to another is not altered.

Refer to our tutorial on view transitions for an overview of display transitions.

Syntax and descriptors of @view-transition.

  • @view-transition: { types: fondu; }

    The types descriptor defines the identifier for the transition. Each page can therefore use a specific transition effect. Several types can be enumerated, separated by commas.

    /* Enable cross-page view transitions */ @view-transition {navigation:auto; types:fondu;} /* Definition of animations */ @keyframes fondu-old { from {transform:opacity(100%);} to {transform:opacity(0%);} } @keyframes fondu-new { from {transform:opacity(0%);} to {transform:opacity(100%);} } /* Applying animations to pseudo-elements */ :active-view-transition-type(fondu)::view-transition-old(root) { animation:fondu-old 2s; } :active-view-transition-type(fondu)::view-transition-new(root) { animation:fondu-new 2s; }

Overview of view transitions.

The relatively new technique of view transitions allows you to define a transition between two displays, instead of from a sudden jump from one display to another. For example, it is possible to set a fade effect between two images.

Here's an example so you can understand what we're talking about right away: a bit of Javascript code allows you to flip the playing cards by clicking on them. The first card flips over without a transition effect. The second, on the other hand, implements a display transition: a fade between the image of the map and the that of the back. Of course, this will only work if the browser you're viewing this page on supports view transitions, which is far from not guaranteed. For example, at this time (2024) Firefox   does not address this feature.

joker
No transition effect
joker
With a transition effect

 

The Javascript code itself is very simple: it simply modifies the source (src attribute) of the img tag. The element on which to act (the map) is passed as the el parameter.

function turnCard(el) { el.src='chemin/image.png'; }

To bring in the transition effect, you just have to modify the code slightly: call the processing via the startViewTransition() method.

function turnCardVT(el) { document.startViewTransition({ update:() => turnCard(el), types:['root'] }); } /* Or, for those who don't like arrow syntaxes */ function turnCardVT(el) { document.startViewTransition({ update: function() { turnCard(el); }, types:['root'] }); }

So we can see that it is very easy to get a nice ergonomics with a very simple code. Here's what the browser does when it make a view transition:

  1. Store a copy of the initial screen as an image.
  2. Make the requested changes.
  3. Memorize a copy of the new screen, also in the form of an image.
  4. Start an animation on the starting frame and the final frame.

The ::view-transition-old() and ::view-transition-new() pseudo-elements.

These two pseudo-elements target the screenshot before editing, and the screenshot after editing, respectively. And of course, these selectors can be used to apply styles to both of these images.
A very simple example is to change the duration of the animations.

Note 1: The same properties must often be applied to both pseudo-elements to obtain a consistent result.
Note 2: The term root means that these styles apply to the entire page during a transition, not just to certain elements.

::view-transition-old(root) { animation-duration:2s; } ::view-transition-new(root) { animation-duration:2s; }

 

But it's possible to do much more sophisticated things, such as defining new animations entirely.
Note: These codes are given to you in principle. They would work on a page with a single display transition, but on this page has many of them, and they will have to be completed as we will see a little later.

king
@keyframes rotation-old { from {transform:rotate(0deg); opacity:1;} to {transform:rotate(360deg); opacity:0;} } @keyframes rotation-new { from {transform:rotate(0deg); opacity:0;} to {transform:rotate(360deg); opacity:1;} } ::view-transition-old(root) { animation:rotation-old 1s; } ::view-transition-new(root) { animation:rotation-new 1s; }
king
@keyframes zoom-old { from {transform:scale(1);} to {transform:scale(0);} } @keyframes zoom-new { from {transform:scale(0);} to {transform:scale(1);} } ::view-transition-old(root) { animation:zoom-old 1s; } ::view-transition-new(root) { animation:zoom-new 1s; }

Very often animations change the opacity property because it is absolutely necessary that the image of the old screen disappears for that the new screen appears. This is done by varying their opacity:

  • Changing the opacity from 1 to 0 on ::view-transition-old(),
  • Changing the opacity from 0 to 1 on ::view-transition-new().

The view-transition-name property.

By default, animations are applied to the entire page (root element). In the case of a fade transition, it's not a problem because the elements that are not modified are replaced by themselves: nothing is seen. But other animations cannot be applied to the root element.

The view-transition-name property allows you to isolate an element and apply animations to that element only, leaving the the rest of the document outside the animation. This is done by associating an element with a transition identifier. This identifier is then found in the parameter pseudo-elements ::view-transition-old() and ::view-transition-new().

#logo {view-transition-name: demo-name;} ::view-transition-old(demo-name) { ... } ::view-transition-new(demo-name) { ... }
Back
queen
Here, the animation chosen is a rotation. By default, it applies to the entire page
Back
queen
The title and map have each been given a transition ID and different animations.

The :active-view-transition pseudo class.

This pseudo class targets the root element (:root) when a display transition is in progress. It no longer targets anything once the transition is complete. In the example below, we used it to blur the page while the card flips.

This pseudo-class can of course be combined with another selector so as not to target the entire page.

queen
:active-view-transition {filter:blur(5px);}

Multiple view transitions on the same page.

By default, all page transition effects are triggered at the same time. But it is often necessary to have several transition effects on the same page. To do this, it will be necessary to:

  • Associate a transition name with each of the elements that are the object of a transition. This is the role of the view-transition-name property.
    Without using the view-transition-name property, the default name is root.
  • Identify the type of transition you want in the Javascript code, with the types parameter, and use the pseudo-class :active-view-transition-type() in CSS code.

    script function turnCardVT(el) { document.startViewTransition({ update:() => turnCard(el), types:['demo-type'] }); } /script style :active-view-transition-type(demo-type)::view-transition-old(demo-name) { ... } :active-view-transition-type(demo-type)::view-transition-new(demo-name) { ... } /style

queen

In summary, here's the code needed for this last example, and for it to work without interacting with the other view transitions set to this page.

/* The function is called by clicking on the card */ /* onclick="turnCardVT(this, 'fondu')" */ script id="tutorial1-js" function turnCardVT(el,type) { if (document.startViewTransition) { document.startViewTransition({ update:() => turnCard(el), types:[type] }); } else { alert('Navigateur non compatible.'); } } function turnCard(el) { if(el.src.indexOf('back')==-1) { el.src='img/@view-transition-back.png'; } else { el.src='img/@view-transition-' + el.alt + '.png'; } } /script style @keyframes fondu-old{ from {filter:brightness(100%);} to {filter:brightness(10%);} } @keyframes fondu-new{ from {filter:brightness(10%);} to {filter:brightness(100%);} } #tutorial5 {view-transition-name:tutorial5;} :root:active-view-transition-type(fondu)::view-transition-old(tutorial5) { animation:fondu-old 1s; } :root:active-view-transition-type(fondu)::view-transition-new(tutorial5) { animation:fondu-new 1s; } /style

Cross Document View Transition.

IIt is possible, using a comparable mechanism, to define a view transition when one page replaces another. That is to say, every time whether a user clicks on a link, uses the back button, or chooses a page from favorites.

The constraint is that these two pages must be on the same domain.

The basic solution is simple to implement: both pages must have the @view-transition directive in their CSS code. Each of them must also define the animation to run after the page loads. If all pages are displayed to the same effect, it is common to write CSS styles in a separate file, with each page referencing this file with a link tag in their header.
Here's an example of minimal code.

@view-transition {navigation: auto;} @keyframes navigate-old { from {transform:translate(0);} to {transform:translate(100%);} } @keyframes navigate-new { from {transform:translate(-100%);} to {transform:translate(0px);} } ::view-transition-old(root) { animation:navigate-old 1s; } ::view-transition-new(root) { animation:navigate-new 1s; }

The link below takes you to a page with this code. If you are using a compatible browser, this will give you an idea of the result: demo link.

In short.

Browsers compatibility.

Column 1
Support for on-page display transitions (not from page to page). Corresponding to level 1 of the specification.
Column 2
Support for the @view-transition directive to establish a transition between pages (Level 2 of the specification).
1
View
transition
2
@view-transition
at-rule
Estimated overall support.
86%
80%

Browsers on computers :

Mobile browsers :

Outdated or marginal browsers :

Internet Explorer

UC Browser pour Androïd

Opéra Mobile

QQ Browser

Baidu Browser

Opéra

Firefox pour Androïd

Firefox

Androïd Brower

Chrome pour Androïd

Samsung Internet

Safari

Safari sur IOS

Chrome

Edge

KaiOS Browser

Opéra mini

@view-transition at rule historic.

  • CSS View Transitions Module Level 2

    Level 2 of the specification introduces the possibility of defining view transitions between several documents, thanks to the new @view-transition at-rule.
    WD
    May 16, 2024
    Working Draft.
    CR
    PR
    REC

See also, about view transitions.

The specification on view transitions (CSS View Transitions Module) is mostly rich in selectors (pseudo-elements and pseudo-classes).

Selectors:

::view-transition
Langue française
Pseudo-element targeting elements during the time of a viewtransition.
::view-transition-group()
Langue française
Targets a group of elements created during a view transition.
::view-transition-image-pair()
Langue française
Targets the two screenshots taken for the purposes of a view transition.
::view-transition-new()
Langue française
Targets the screenshot of the new state, in the case of a View Transition.
::view-transition-old()
Langue française
Targets the screenshot of the previous state, in the case of a view transition.
:active-view-transition
Langue française
Targets the root of the document, during a view transition.
:active-view-transition-type()
Langue française
Targets the root of the document, during a view transition of a certain type.

Properties:

view-transition-name
Langue française
Associates a transition identifier with the targeted element.