https://twitter.com/emilkowalski_/status/1592997196911501312
If you’re like most people, you probably saw this tweet and thought it was ✨ magic ✨ It’s been some time since I wrote some CSS, so I thought I’d give reproducing the effect a go.
https://codepen.io/aarohmankad/pen/eYKrxqm
The comments gave me a small hint towards how to accomplish this:
https://twitter.com/artur_bien/status/1593021503259672576
So I started with two identical DOM trees, and some pretty basic light/dark mode CSS. (We’ll toggle the classes on the body
tag later.)
<body class="lightMode">
<div class="dark">
hello
<button>toggle</button>
</div>
<div class="light">
hello
<button>toggle</button>
</div>
</body>
body {
margin: 0;
padding: 0;
}
body > div.light {
background: white;
color: black;
}
body > div.dark {
background: black;
color: white;
}
body > div {
position: absolute;
height: 100%;
width: 100%;
}
This will render the light mode on top of the dark mode, and I was planning on using the clip-path
to transition between the two of them. First, understanding the clip-path
API enough to make some animations. From the examples on MDN, I saw that I could use the inset
option to set some keyframes. Some experimentation led to this
@keyframes down-enter {
0% {
clip-path: inset(0 0 100% 0);
}
100% {
clip-path: inset(0);
}
}
@keyframes down-leave {
0% {
clip-path: inset(0);
}
100% {
clip-path: inset(100% 0 0 0);
}
}
We’ll add an on click handler to the DOM to let us toggle between the dark and light mode states.
document.querySelectorAll("button").forEach((b) =>
b.addEventListener("click", () => {
document.querySelector("body").classList.toggle("darkMode");
document.querySelector("body").classList.toggle("lightMode");
})
);
Now that we’re toggling all the CSS classes properly, we can add some transitions between the two states
body.darkMode > div.dark {
animation: 1s down-enter;
}
body.darkMode > div.light {
animation: 1s down-leave;
}
body.lightMode > div.light {
animation: 1s down-enter;
}
body.lightMode > div.dark {
animation: 1s down-leave;
}
However, at this point you’ll notice a small flicker after toggling between states.