DigitalOcean provides cloud products for every stage of your journey. Get started with $200 in free credit!
The CSS ::view-transition
pseudo-element is the top-level — or “root” — containing all animated transitions defined as CSS view transitions on the page.
::view-transition {
position: fixed;
inset: 0;
}
Syntax
::view-transition {
/* Styles */
}
It’s worth noting that ::view-transition
holds all view transitions on the page (we’ll get to that in a bit), so you’re likely to see it used most often used unchained to a selector like the example above rather than, say, this:
/* 👎 */
blockquote::view-transition {
/* Styles */
}
Left as-is, ::view-transition
is scoped to the <html>
element:
html::view-transition {
/* Styles */
}
Default styles
Like many semantic HTML elements and pseudo-elements, browsers apply a set of default styles to ::view-transition
.
::view-transition {
position: fixed;
inset: 0;
}
So, if we want to position ::view-transition
ourselves, these are the styles we have to override in our own stylesheet.
It’s a “tree-abiding” pseudo-element
In other words, it’s effectively a wrapper that serves as the parent pseudo-element for others below it. The spec calls this a “tree-abiding pseudo-element” which means it contains other pseudos that can be used to style view transitions directly in CSS.
In this case, ::view-transition
contains all of the view transitions on the page, organized in groups.
::view-transition
├─ ::view-transition-group(name)
│ └─ ::view-transition-image-pair(name)
│ ├─ ::view-transition-old(name)
│ └─ ::view-transition-new(name)
├─ ::view-transition-group(name)
│ └─ ::view-transition-image-pair(name)
│ ├─ ::view-transition-old(name)
│ └─ ::view-transition-new(name)
│ /* and so one... */
This way, we can define styles that apply to all view transitions together with ::view-transition
and individually with ::view-transition-group
.
How it fits into the view transitions process
It’s a good idea to be familiar with the steps that a view transition takes for context on where this ::view-transition
tree fits in with everything.
- A view transition is activated with
document.startViewTransition()
in JavaScript. - Whatever transition we’re passing to
startViewTransition
is triggered to begin transitioning between views. - The browser takes a picture, or snapshot, of the new view’s state that will be transitioned to.
- The
::view-transition
tree is established, defining styles used in the transition. - The old view fades out while the new view fades in.
- The transition wraps up once the
ViewTransition.finished
promise is made in JavaScript.
It’s right there in Step 4 that we’re talking about.
It introduces a new stacking layer!
You know how we can use the CSS z-index
property to layer elements one on top of another, like in a three-dimensional space?
We call this a “stacking context” and it happens when we declare a position
on an element. In this case, both .child
elements are in a stacking context where we’re using z-index
to determine which element is above the other in the stack. CSS uses this information to determine in what order it applies styles:
- Elements with a negative stack level, typically elements with
z-index: -1
- Elements with a
position
value ofstatic
. - Elements with a stack level of
0
, typically positioned elements with az-index
value ofauto
. - Elements with positive stack levels, e.g. a positioned element with a
z-index
value of1
or higher.
That third layer is called the “top layer” since it’s right smack dab in between layers positive and negative layers. This is where the <html>
and <body>
sit.
Well, it turns out that ::view-transition
introduces a new stacking layer of its own, that is applied after everything else, i.e., it comes after the layer with the highest number:
- Elements with a negative stack level, typically elements with
z-index: -1
- Elements with a
position
value ofstatic
. - Elements with a stack level of
0
, typically positioned elements with az-index
value ofauto
. - Elements with positive stack levels, e.g. a positioned element with a
z-index
value of1
or higher. - View transitions
Here’s exactly how the specification describes it:
The
CSS View Transitions Module Level 1, 4.2. View Transition Painting Order::view-transition
pseudo-element generates a new stacking context, called the view transition layer, which paints after all other content of the document (including any content rendered in the top layer), after any filters and effects that are applied to such content. (It is not subject to such filters or effects, except insofar as they affect the rendered contents of the ::view-transition-old() and ::view-transition-new() pseudo-elements.)
What’s the big deal, you ask? This means that a view transition’s styles are painted after everything else, ensuring that they are never buried beneath other layers. This way, we never have to juggle between view transition styles and the styles of the elements on a page with z-index
to make sure they’re visible. But this only takes effect if (1) there are view transitions on the page and (2) when the view transition is running. Once the transition ends, its stacking context is gone.
Specification
The CSS ::view-transition
pseudo-element is defined in the View Transitions Module Level 1 specification. It’s labeled a Candidate Recommendation Snapshot which means it’s been widely reviewed and is intended to become an official W3C Recommendation, but is still being tested in the wild.
The specification further states:
This document is intended to become a W3C Recommendation; it will remain a Candidate Recommendation at least until 5 December 2023 to gather additional feedback.
That date has passed as of this writing, so keep an eye on the document’s status as it makes its way toward becoming a recommended feature.
Browser support
If you need to support older browsers that do not support ::view-transition
, try using @supports
to check whether or not the browser recognizes the view-transition-name
property:
/* Apply these styles only if View Transitions are *NOT* supported */
@supports not (view-transition-name: none) {
/* Fallback Styles */
}