<div id="app">
<h1>View Transition API - Sliding Effect Demo</h1>
<div v-if="page === 0">
<h2>Page 0</h2>
<hr>
<button type="button" @click="changePage(1)">
Page 1
</button>
<hr>
<p>Here we've created a custom CSS animation and applied it to the ::view-transition-old(figure-caption) and ::view-transition-new(figure-caption) pseudo-elements. We've also added a number of other styles to both to keep them in the same place and stop the default styling from interfering with our custom animations.</p>
</div>
<div v-if="page === 1">
<h2>Page 1</h2>
<hr>
<button type="button" @click="changePage(0)">
Page 0
</button>
<button type="button" @click="changePage(2)">
Page 2
</button>
<hr>
<p>Note that we also discovered another transition option that is simpler and produced a nicer result than the above. Our final view transition ended up looking like this:</p>
</div>
<div v-if="page === 2">
<h2>Page 3</h2>
<hr>
<button type="button" @click="changePage(1)">
Page 1
</button>
<hr>
<p>This works because, by default, ::view-transition-group transitions width and height between the old and new views. We just needed to set a fixed height on both states to make it work.</p>
</div>
</div>
:root {
background: #fff;
}
::view-transition-old(root) {
animation-duration: 0.8s;
animation-name: slide-out;
mix-blend-mode: normal;
}
::view-transition-new(root) {
animation-duration: 0.8s;
animation-name: slide-in;
box-shadow: 0 0 40px #0003;
mix-blend-mode: normal;
}
.back::view-transition-old(root) {
animation-duration: 0.8s;
animation-name: back-slide-out;
box-shadow: 0 0 40px #0003;
mix-blend-mode: normal;
}
.back::view-transition-new(root) {
animation-duration: 0.8s;
animation-name: back-slide-in;
mix-blend-mode: normal;
}
@keyframes slide-out {
from {
left: 0%;
}
to {
left: -40%;
}
}
@keyframes slide-in {
from {
left: 100%;
}
to {
left: 0%;
}
}
@keyframes back-slide-out {
from {
left: 0%;
z-index: 10000;
}
to {
left: 100%;
z-index: 10000;
}
}
@keyframes back-slide-in {
from {
left: -40%;
}
to {
left: 0%;
}
}
if (!document.startViewTransition) {
document.startViewTransition = (fn) => {
fn()
}
}
const { createApp, ref } = Vue
createApp({
setup() {
const page = ref(0)
function changePage (p) {
let back = null
if (page.value < p) {
back = false
} else if (page.value > p) {
back = true
} else {
return
}
document.startViewTransition(() => {
if (back) {
document.documentElement.classList.add('back')
} else {
document.documentElement.classList.remove('back')
}
page.value = p
})
}
return {
changePage,
page
}
}
}).mount('#app')
This Pen doesn't use any external CSS resources.