Effecto de cambio de modo claro-oscuro
Theme toggle effect ALL effects
/* circle */
::view-transition-group(root) {    animation-timing-function: var(--expo-out);}::view-transition-old(root),.dark::view-transition-old(root) {    animation: none;    z-index: -1;}::view-transition-new(root) {    mask: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40"><circle cx="20" cy="20" r="20" fill="white"/></svg>')        center / 0 no-repeat;    animation: scale 1s;}@keyframes scale {    to {        mask-size: 200vmax;    }}
/* circle-with-blur */
::view-transition-group(root) {    animation-timing-function: var(--expo-out);}::view-transition-new(root) {    mask: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40"><defs><filter id="blur"><feGaussianBlur stdDeviation="2"/></filter></defs><circle cx="20" cy="20" r="18" fill="white" filter="url(%23blur)"/></svg>')        center / 0 no-repeat;    animation: scale 1s;}::view-transition-old(root),.dark::view-transition-old(root) {    animation: none;    z-index: -1;}.dark::view-transition-new(root) {    animation: scale 1s;}@keyframes scale {    to {        mask-size: 200vmax;    }}
/* circle-blur-top-left */
::view-transition-group(root) {    animation-timing-function: var(--expo-out);}::view-transition-new(root) {    mask: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40"><defs><filter id="blur"><feGaussianBlur stdDeviation="2"/></filter></defs><circle cx="0" cy="0" r="18" fill="white" filter="url(%23blur)"/></svg>')        top left / 0 no-repeat;    mask-origin: content-box;    animation: scale 1s;    transform-origin: top left;}::view-transition-old(root),.dark::view-transition-old(root) {    animation: scale 1s;    transform-origin: top left;    z-index: -1;}@keyframes scale {    to {        mask-size: 350vmax;    }}
/* polygon */
::view-transition-group(root) {    animation-duration: 0.7s;    animation-timing-function: var(--expo-out);}::view-transition-new(root) {    animation-name: reveal-light;}::view-transition-old(root),.dark::view-transition-old(root) {    animation: none;    z-index: -1;}.dark::view-transition-new(root) {    animation-name: reveal-dark;}@keyframes reveal-dark {    from {        clip-path: polygon(50% -71%, -50% 71%, -50% 71%, 50% -71%);    }    to {        clip-path: polygon(50% -71%, -50% 71%, 50% 171%, 171% 50%);    }}@keyframes reveal-light {    from {        clip-path: polygon(171% 50%, 50% 171%, 50% 171%, 171% 50%);    }    to {        clip-path: polygon(171% 50%, 50% 171%, -50% 71%, 50% -71%);    }}
/* polygon-gradient */
::view-transition-group(root) {    animation-timing-function: var(--expo-out);}::view-transition-new(root) {    mask: url('assets/custom-svg.svg') top left / 0 no-repeat;    mask-origin: top left;    animation: scale 1.5s;}::view-transition-old(root),.dark::view-transition-old(root) {    animation: scale 1.5s;    z-index: -1;    transform-origin: top left;}@keyframes scale {    to {        mask-size: 200vmax;    }}
/* gif-1 */
::view-transition-group(root) {    animation-timing-function: var(--expo-in);}::view-transition-new(root) {    mask: url('https://media.tenor.com/cyORI7kwShQAAAAi/shigure-ui-dance.gif') center / 0 no-repeat;    animation: scale 3s;}::view-transition-old(root),.dark::view-transition-old(root) {    animation: scale 3s;}@keyframes scale {    0% {        mask-size: 0;    }    10% {        mask-size: 50vmax;    }    90% {        mask-size: 50vmax;    }    100% {        mask-size: 2000vmax;    }}
/* gif-2 */
::view-transition-group(root) {    animation-timing-function: var(--expo-in);}::view-transition-new(root) {    mask: url('https://media.tenor.com/Jz0aSpk9VIQAAAAi/i-love-you-love.gif') center / 0 no-repeat;    animation: scale 2s;}::view-transition-old(root),.dark::view-transition-old(root) {    animation: scale 2s;}@keyframes scale {    0% {        mask-size: 0;    }    10% {        mask-size: 50vmax;    }    90% {        mask-size: 50vmax;    }    100% {        mask-size: 2000vmax;    }}
/* animation timing functions */:root {    --expo-in: linear(        0 0%,        0.0085 31.26%,        0.0167 40.94%,        0.0289 48.86%,        0.0471 55.92%,        0.0717 61.99%,        0.1038 67.32%,        0.1443 72.07%,        0.1989 76.7%,        0.2659 80.89%,        0.3465 84.71%,        0.4419 88.22%,        0.554 91.48%,        0.6835 94.51%,        0.8316 97.34%,        1 100%    );    --expo-out: linear(        0 0%,        0.1684 2.66%,        0.3165 5.49%,        0.446 8.52%,        0.5581 11.78%,        0.6535 15.29%,        0.7341 19.11%,        0.8011 23.3%,        0.8557 27.93%,        0.8962 32.68%,        0.9283 38.01%,        0.9529 44.08%,        0.9711 51.14%,        0.9833 59.06%,        0.9915 68.74%,        1 100%    );}if (!document.startViewTransition) switchTheme()document.startViewTransition(switchTheme)Here’s some demos Now you can write your css as you wish to
following is a simple example, that uses a circular mask
::view-transition-new(root) {    mask: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40"><circle cx="20" cy="20" r="20" fill="white"/></svg>')        center / 0 no-repeat;    animation: scale 1s;}
::view-transition-old(root),.dark::view-transition-old(root) {    animation: none;    z-index: -1;}.dark::view-transition-new(root) {    animation: scale 1s;}
@keyframes scale {    to {        mask-size: 200vmax;    }}lets add a little blur to the svg
::view-transition-group(root) {    animation-timing-function: var(--expo-out);}
::view-transition-new(root) {    mask: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40"><defs><filter id="blur"><feGaussianBlur stdDeviation="2"/></filter></defs><circle cx="20" cy="20" r="18" fill="white" filter="url(%23blur)"/></svg>')        center / 0 no-repeat;    animation: scale 1s;}
::view-transition-old(root),.dark::view-transition-old(root) {    animation: none;    z-index: -1;}.dark::view-transition-new(root) {    animation: scale 1s;}
@keyframes scale {    to {        mask-size: 200vmax;    }}let’s try to pivot the center of the circle to top left
::view-transition-group(root) {    animation-timing-function: var(--expo-out);}
::view-transition-new(root) {    mask: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40"><defs><filter id="blur"><feGaussianBlur stdDeviation="2"/></filter></defs><circle cx="0" cy="0" r="18" fill="white" filter="url(%23blur)"/></svg>')        top left / 0 no-repeat;    mask-origin: content-box;    animation: scale 1s;    transform-origin: top left;}
::view-transition-old(root),.dark::view-transition-old(root) {    animation: scale 1s;    transform-origin: top left;    z-index: -1;}
@keyframes scale {    to {        mask-size: 350vmax;    }}see this is simple, now the skylimit is your imagination
we’ve seen all the svg mask animations, but we can use clip-paths too
::view-transition-group(root) {    animation-duration: 0.7s;    animation-timing-function: var(--expo-out);}
::view-transition-new(root) {    animation-name: reveal-light;}
::view-transition-old(root),.dark::view-transition-old(root) {    animation: none;    z-index: -1;}.dark::view-transition-new(root) {    animation-name: reveal-dark;}
@keyframes reveal-dark {    from {        clip-path: polygon(50% -71%, -50% 71%, -50% 71%, 50% -71%);    }    to {        clip-path: polygon(50% -71%, -50% 71%, 50% 171%, 171% 50%);    }}
@keyframes reveal-light {    from {        clip-path: polygon(171% 50%, 50% 171%, 50% 171%, 171% 50%);    }    to {        clip-path: polygon(171% 50%, 50% 171%, -50% 71%, 50% -71%);    }}the issue with using clip path is that you can’t do much with it, like adding gradient or blur. so svg should be a good choice for most cases
lets see how can we improve the clip-path animation with a custom svg with linear gradient
we can use local assets too
::view-transition-group(root) {    animation-timing-function: var(--expo-out);}
::view-transition-new(root) {    mask: url('assets/custom-svg.svg') top left / 0 no-repeat;    mask-origin: top left;    animation: scale 1.5s;}
::view-transition-old(root),.dark::view-transition-old(root) {    animation: scale 1.5s;    z-index: -1;    transform-origin: top left;}
@keyframes scale {    to {        mask-size: 200vmax;    }}here’s the cool part
you can use gifs too
::view-transition-group(root) {    animation-timing-function: var(--expo-in);}
::view-transition-new(root) {    mask: url('https://media.tenor.com/cyORI7kwShQAAAAi/shigure-ui-dance.gif') center / 0 no-repeat;    animation: scale 3s;}
::view-transition-old(root),.dark::view-transition-old(root) {    animation: scale 3s;}
@keyframes scale {    0% {        mask-size: 0;    }    10% {        mask-size: 50vmax;    }    90% {        mask-size: 50vmax;    }    100% {        mask-size: 2000vmax;    }}this one’s good 😉
::view-transition-group(root) {    animation-timing-function: var(--expo-in);}
::view-transition-new(root) {    mask: url('https://media.tenor.com/Jz0aSpk9VIQAAAAi/i-love-you-love.gif') center / 0 no-repeat;    animation: scale 1.5s;}
::view-transition-old(root),.dark::view-transition-old(root) {    animation: scale 1.5s;}
@keyframes scale {    0% {        mask-size: 0;    }    10% {        mask-size: 50vmax;    }    90% {        mask-size: 50vmax;    }    100% {        mask-size: 2000vmax;    }}here are the two animation timing functions i’m using for the examples
:root {    --expo-in: linear(        0 0%,        0.0085 31.26%,        0.0167 40.94%,        0.0289 48.86%,        0.0471 55.92%,        0.0717 61.99%,        0.1038 67.32%,        0.1443 72.07%,        0.1989 76.7%,        0.2659 80.89%,        0.3465 84.71%,        0.4419 88.22%,        0.554 91.48%,        0.6835 94.51%,        0.8316 97.34%,        1 100%    );    --expo-out: linear(        0 0%,        0.1684 2.66%,        0.3165 5.49%,        0.446 8.52%,        0.5581 11.78%,        0.6535 15.29%,        0.7341 19.11%,        0.8011 23.3%,        0.8557 27.93%,        0.8962 32.68%,        0.9283 38.01%,        0.9529 44.08%,        0.9711 51.14%,        0.9833 59.06%,        0.9915 68.74%,        1 100%    );}thats basically it. you have enough context to build cool theme transitions with view transitions api