Shots in this scene
Styling the Pseudo-Elements
In one line
The browser builds a tree of pseudo-elements you can style like any element: change the group's timing, replace the old and new pictures' animations, and use transition types to choose a different animation for each direction.
Think of it like this
A film editor keeps the clips and changes only the transition between them: a wipe for scene changes, a slow dissolve for time passing. The transition is separate from the footage, so you can restyle it without touching either clip.
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- ::view-transition-group(name)
- The pseudo-element that moves and resizes from the old box to the new box of one named element.
- ::view-transition-old / new
- The old and new pictures inside a group: the old fades out, the new fades in.
- transition type
- A label on one transition (such as
forwards) so CSS can pick different animations. - custom property
- A CSS variable such as
--slide. Keyframes can read it.
Step by step
01Change only the timing
One line, ::view-transition-group(volt) { animation-duration: 600ms }, changed a whole morph in Topic 11.2. The pictures inherit it: try it first.
02Replace the pictures' animation
The tab example sets animation: out 200ms ease-in both on old(panel) and in 300ms ease-out both on new(panel): leaving is faster than arriving (Phase 5).
03Pick the direction with a type
Press Next, then Back. The console prints types: forwards, then types: backwards; the panel leaves left, then right, from one keyframe pair.
04Flip it, calm it
Tick "right-to-left" and press Next: the panel leaves toward the right. Turn on the timeline's Reduced motion: it only fades.
Try it yourself
- 1
Read the half-way transform
Press Pause, Next, then Step until
old(panel)is half done (100 ms of 200). Measured with the animation paused at 100 ms:translateX(-18.9px), opacity 0.68. - 2
Remove the type rule
Delete
:root:active-view-transition-type(backwards) { --way: -1; }. Both directions leave to the left, because--waystays 1; the console still prints the types, but nothing reads them.
Code & diagrams
Press Next and Back with the timeline paused and step. At step 1 Back does nothing: no change means no transition.
Nothing is moving yet. Hover, click or scroll the page: every animation it starts shows up here as a track.
Console
Nothing logged yet.Expected console output
at the end: no change, no transition
types: forwardsThe old page stays still (`animation: none`) and a circle grows over it. old(page) has no animation, so the console list omits it.
Nothing is moving yet. Hover, click or scroll the page: every animation it starts shows up here as a track.
Console
Nothing logged yet.Expected console output
::view-transition-group(page) ::view-transition-group(root) ::view-transition-new(page) ::view-transition-new(root) ::view-transition-old(root)Break it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
Start a second transition while the first runs
Add a second go(1) call after the first at the bottom of the direction example.
Myth vs fact
Myth
I need JavaScript to make a different transition for each direction.
Fact
One line says the direction (types: ['forwards']). The animation stays in CSS, selected by :active-view-transition-type().
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
Types can change while the transition runs (
t.types.add('x')worked in our test) and are not cleared afterfinished: read them only from the transition object you hold. - ▸
The group is the only animation that moves a box, so the timeline colours it as layout cost. It runs on the browser's snapshot layer, not your page's layout: measure with Phase 6's tools before avoiding names.
Remember this
- 1
The problem this solves: the default 250 ms cross-fade suits nothing in particular. A tab you move forwards should leave to the left, one you move back to the right, and a hero should morph slower than a page fades.
- 2
Recall from Topics 11.1 and 11.2: a transition photographs the old page, runs your update and photographs the new page; a
view-transition-namemakes an element its own group, paired with the same name in the other state. - 3
The tree. While a transition runs,
::view-transitionsits on the root element. Inside it, one::view-transition-group(name)per name; inside each,::view-transition-image-pair(name), and inside that::view-transition-old(name)and::view-transition-new(name).nameisrootfor the page. All take ordinary CSS (animation,clip-path,mix-blend-mode). The pictures take their timing from the group unless you set their own, andanimation: noneshows a picture in its final state all the time (the wipe example keeps the old page still). - 4
Types choose the animation per transition.
document.startViewTransition({ update, types: ["forwards"] })labels this call. While it runs,:active-view-transition-type(forwards)matches the root element. The tab example sets one custom property,--way, to-1forbackwards, and one keyframe pair reads it: the code that knows the direction says it, the CSS decides how it looks. - 5
Right-to-left pages. "Forwards" means toward the end of reading, so the slide flips. The example uses
--slide: 1, set to-1under:root[dir="rtl"]. Measured at half of the old panel's 200 ms:translateX(-18.9px)left-to-right,translateX(18.9px)right-to-left. We use thedirattribute on purpose: a Vite 8 production CSS build removed a:root:dir(rtl)rule in testing. - 6
Reduced motion. Keep the fade, drop the movement:
@media (prefers-reduced-motion: reduce) { :root { --slide: 0; } }. Measured: the old panel's transform ismatrix(1, 0, 0, 1, 0, 0)at half the animation while its opacity is still 0.68, so it only cross-fades.
Explain it without notes
How do you slide left going forwards and right going back, without two copies of the keyframes?
How should a slide behave on a right-to-left page and for a visitor on reduced motion?
Practice
Make a wizard's steps slide forwards and backwards, flip on right-to-left and only fade on reduced motion, with one pair of keyframes.
The page cross-fade (root) should take 150 ms while a named hero morphs for 500 ms. Write the CSS.
Done when you can
You can name the pseudo-elements in the tree and say what each animates
You can pick keyframes per direction with a type and a custom property
You can flip a slide for right-to-left pages and calm it for reduced motion