Types
There are multiple built in transitions you can utilize. These can be used individually per anchor link or you can set them globally.
- cross-fade
- slide-right
- slide-left
- expand-from-element
- expand-from-element-back
<!-- Set globally --> <meta name="view-transition" content="slide-left"> <meta name="view-transition-back" content="slide-right"> <!-- Set transition on anchor link These will override the global settings --> <a href="/" view-transition="cross-fade">Welcome</a> <mc-card href="/item/123" view-transition="expand-from-element"></mc-card> <!-- Add a back transition Back will only work after the initial view-transition --> <a href="/" view-transition="expand-from-element" view-transition-back="expand-from-element-back">Welcome</a> <a href="/" view-transition="slide-left" view-transition-back="slide-right">Welcome</a>
Custom view transitions
You can add your own view transitions. Both CSS and code transitions are supported.
/* Use standard css */ ::view-transition-old(slide-left) { animation: page-slide-left-out; animation-duration: 400ms; animation-timing-function: ease; } ::view-transition-new(slide-left) { animation: page-slide-left-in; animation-duration: 400ms; animation-timing-function: ease; } @keyframes page-slide-left-in { 0% { transform: translateX(100%); clip-path: inset(0px 100% 0px 0px); } 100% { transform: translateX(0px); clip-path: inset(0px 0px 0px 0px); } } @keyframes page-slide-left-out { 0% { transform: translateX(0px); clip-path: inset(0px 0px 0px 0px); } 100% { transform: translateX(-100%); clip-path: inset(0px 0px 0px 100%); } }
import { registerViewTransition } from '@thewebformula/lithe'; registerViewTransition('the-name', { setup(container, target) { const scrollTop = document.documentElement.scrollTop; document.documentElement.style.setProperty('--mc-view-transition-scroll-fix', `translateY(-${scrollTop}px)`); const containerBounds = container.getBoundingClientRect(); const targetBounds = target.getBoundingClientRect(); return { containerBounds, targetBounds, scrollTop }; }, animate(container, { containerBounds, targetBounds, scrollTop }) { document.documentElement.animate( [ { transform: `translate(${targetBounds.x - containerBounds.x}px, ${targetBounds.y - containerBounds.y - scrollTop}px)`, height: `${targetBounds.height}px`, width: `${targetBounds.width}px` }, { transform: `translate(0px, 0px)`, height: `${container.offsetHeight}px`, width: `${container.offsetWidth}px`, } ], { duration: 400, easing: 'cubic-bezier(0.2, 0, 0, 1)', pseudoElement: '::view-transition-new(expand-from-element)' } ); } });