safe View Transition
Use the awesome, experimental View Transitions API safely, without needing to worry about whether it's available, or whether the user prefers reduced motion.
Allergic to copy-pasting code, or just want to make your node_modules
more
massive? Install this via npm
here.
typescriptjavascript
// This block of code stops of the transition from happening if the user
// doesn't want it
const motionSafeMediaQuery = window.matchMedia(
'(prefers-reduced-motion: no-preference)'
)
let motionSafe = motionSafeMediaQuery.matches
motionSafeMediaQuery.onchange = () => {
motionSafe = motionSafeMediaQuery.matches
}
export type ViewTransitionCallback = () => void | Promise<void>
type ObjectWithStartViewTransition = {
startViewTransition: (callback: ViewTransitionCallback) => void
}
export function safeViewTransition(callback: ViewTransitionCallback) {
if (
motionSafe &&
typeof document !== 'undefined' &&
'startViewTransition' in document
) {
// Needed until TypeScript catches up
const doc = document as unknown as ObjectWithStartViewTransition
doc.startViewTransition(callback)
} else {
callback()
}
}
// This block of code stops of the transition from happening if the user
// doesn't want it
const motionSafeMediaQuery = window.matchMedia(
'(prefers-reduced-motion: no-preference)'
)
let motionSafe = motionSafeMediaQuery.matches
motionSafeMediaQuery.onchange = () => {
motionSafe = motionSafeMediaQuery.matches
}
export function safeViewTransition(callback) {
if (
motionSafe &&
typeof document !== 'undefined' &&
'startViewTransition' in document
) {
// Needed until TypeScript catches up
const doc = document
doc.startViewTransition(callback)
} else {
callback()
}
}
Usage
typescriptjavascript
safeViewTransition(() => {
// update the DOM in here, and watch the magic happen!
})
safeViewTransition(() => {
// update the DOM in here, and watch the magic happen!
})
Demo
Try these demoes in browsers that support the View Transitions API (e.g.
Chromium based browsers, including Chrome, Brave, Arc) and ones that don't (e.g.
Safari, Firefox) to see these demos gracefully handle when the API is
unavailable. You can also try emulating the (prefers-reduced-motion: reduce)
media query (in Chrome, open the devtools, hit cmd/ctrl + shift + p
, search
for prefers-reduced-motion
).