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.