CSS View Transitions

(Sane & Not)

Olex Ponomarenko

https://olex.co – October 16, 2023

Support TLDR: Currently requires JS

Chrome ✅  Firefox ❌  Safari ❌  iOS ❌  Android ⚠️

Frameworks support: astro, nuxt*, sveltekit*, remix**

*experimental, **easy to diy

document.startViewTransition(() => {
  // manipulate the dom / change route...
})

Page A

Page B

body {
  view-transition-name: content;
}
.train-one {}
.train-two {
  view-transition-name: train2;
  transform: scaleX(1);
}

::view-transition-group(train2) {
  animation-duration: 4s;
}
body {
  view-transition-name: content;
}
.train-one {}
.train-two {
  view-transition-name: train2;
  transform: translateX(100px)
             scaleX(2);
}
::view-transition-group(train2) {
  animation-duration: 4s;
}

View Transition DOM Structure

::view-transition
├─ ::view-transition-group(content)
│ └─ ::view-transition-image-pair(content)
│     ├─ ::view-transition-old(content)
│     └─ ::view-transition-new(content)
└─ ::view-transition-group(train2)
  └─ ::view-transition-image-pair(train2)
      ├─ ::view-transition-old(train2)
      └─ ::view-transition-new(train2)
  • ::view-transition-old  & -new are images

  • Some animation-{x} properties set by default

View Transition Default CSS

@keyframes -ua-view-transition-fade-in {
  from {
    opacity: 0;
  }
}

html::view-transition-new(*) {
  position: absolute;
  inset-block-start: 0;
  inline-size: 100%;
  block-size: auto;

  animation-name: -ua-view-transition-fade-in;
  animation-duration: inherit;
  animation-fill-mode: inherit;
}

Future Spec:
Same Domain, Opt-in
Without JS Wrapper

Demos

Note: demos are written in astro, but only using it for the wrapping startViewTransition call, not using their polyfill!

CSS View Transitions(Sane & Not)

By Olex Ponomarenko

CSS View Transitions(Sane & Not)

  • 48