so chromium got a new API: the page transition api. tl;dr it allows us to make transitions between pages with almost no effort. if you're into webdev, definetly check out this awesome talk by jake archibald about it. that talk makes me incredibly happy every time i watch it.
anyways i found one really good use case for it today: theme switching. for example, here's the code i use for theming on my new project:
<script lang="ts">
enum Theme { Light, Dark, System }
let theme = +(localStorage.theme ??= Theme.System);
let change = async (target: Theme) => {
localStorage.theme = theme = target;
}
</script>
<svelte:head>
{#if theme === Theme.System}...{/if}
{#if theme === Theme.Dark}...{/if}
{#if theme === Theme.Light}...{/if}
</svelte:head>
{#each ["Light", "Dark", "System"] as name}
<button on:click={() => change(Theme[name])}>
{name}
</button>
{/each}
the important part is the change() function. that just swaps out the CSS files for dark/light theme. but this has two issues:

i've bumped up the latency to 200ms per request and disabled caching, so you can probably guess what's happening: the CSS files need to be loaded first. that gives you a flash of unstyled content. and the obvious thing: it just switches from black to white, which is really unpleasant.
there are a couple of ways we could make this prettier, for example a HTML screenshot library that takes an image and overlay that, or do transition: all, but all of them have huge caveats. but we're here for the transitions API, so lets add two lines of code to the change function:
let change = async (target: Theme) => {
await createDocumentTransition().start(() => {
localStorage.theme = theme = target
});
}
and now it looks like this:

that looks neat, doesn't it? the way the transition API works is that you make a DOM change in the transition.start callback, and it takes a before and an after screenshot, and you can animate them. the default is a crossfade, but you can style that to your heart's content with CSS, and even transition multiple elements independently! also, by animating between the before and after you eliminate the no-CSS flash too! you can achieve this beautiful transition with two (2) lines of code. isn't that beautiful?
also, small note: you should still add 4 more lines to a) check if the user prefers reduced motion, and b) if your browser supports it. that really isn't hard either, this is the production code of change():
let change = async (target: Theme) => {
if (createDocumentTransition && !reducedMotion) {
await createDocumentTransition().start(() => {
localStorage.theme = theme = target
});
} else {
localStorage.theme = theme = target;
}
}
but god damn that's an awesome API, 10/10. good job to the chrome dev team!!!