DEV Community

Cover image for Re-creating Apple’s Dark Mode Icon
Mads Stoumann
Mads Stoumann

Posted on

Re-creating Apple’s Dark Mode Icon

A couple of weeks ago, while fiddling around with my iPhone's Control Center, I noticed a new icon: "Dark Mode":

Apple Dark Mode Icon

I've seen plenty "Dark Mode"-icons — most of them involving the sun and the moon — but this one is so simple and intuitive.

Let's re-create it in SVG, and add some CSS magic!

First, we need a circle:

<circle r="195" cx="200" cy="200" fill="#FFF" stroke="#000" stroke-width="10" />
Enter fullscreen mode Exit fullscreen mode

I've added a black stroke, so the icon works on light backgrounds as well:

Circle

Now, the semi-circle is a bit more complicated. For this, we need an Arc.

In SVG, this is called A, and is within a path:

<path d=" M 200 375 A 175 175 0 0 1 200 2" />
Enter fullscreen mode Exit fullscreen mode

While you can manually code arcs, it's much easier to use a tool for it. Here's an online tool, you can use.

Now, we have this:

SVG Arc

Let's add two more semi-circles

<path d=" M 200 300 A 100 100 0 0 1 200 100" fill="#FFF" />
<path d=" M 200 100 A 100 100 180 0 1 200 300" />
Enter fullscreen mode Exit fullscreen mode

— and we have this:

Complete Icon

Now for the fun part! Let's add a single CSS Custom Property, that can either be 0 or 1:

body {
  --dark-mode: 0;
}
Enter fullscreen mode Exit fullscreen mode

Using this property, we'll set the background-color of the page:

body {
  background-color: hsl(0, 0%, calc(100% * (1 - var(--dark-mode))));
}
Enter fullscreen mode Exit fullscreen mode

In hsl, the third paramter is lightness. 0% is black, while 100% is white. So we'll multiply 100% with either 1 (dark mode on) or 0 (dark mode off).

We'll use the same property to invert and rotate the icon:

.class {
  filter: invert(var(--dark-mode));
  transform: rotate(calc(var(--dark-mode) * 180deg));
}
Enter fullscreen mode Exit fullscreen mode

Now, if you change the --dark-mode-property to 1, the icon will invert and rotate, and the background of the page will change to black:

Dark Mode

How you toggle the property is up to you. The "no-JS"-way could be a checkbox, while the JS-way could be something like this:

element.addEventListener('click', () => {
  const current = document.body.style.getPropertyValue("--dark-mode") - 0;
  document.body.style.setProperty("--dark-mode", 1 - current);
})
Enter fullscreen mode Exit fullscreen mode

First, get the current status using getPropertyValue(). Convert it to a numeric value by subtracting a 0 (old JS-hack!), then set the opposite value using setProperty().

Here's a Codepen demo:

NOTE: In the Codepen, I've added the JS-toggle-function to the svg itself. In production, add proper semantics, like a <button> or similar.

Discussion (6)

Collapse
afif profile image
Temani Afif

If you are interested here is a CSS only solution :)

Collapse
madsstoumann profile image
Mads Stoumann Author

I had a sneaking feeling you’d do that 😁 Great work, as always.

Collapse
link2twenty profile image
Andrew Bone

I started one then thought, I'll just wait for @afif 😅

Thread Thread
madsstoumann profile image
Mads Stoumann Author

Maybe we can push him to add a cool animation to it? 😉

Thread Thread
afif profile image
Temani Afif • Edited on

why not 😉 (I am using :has() which works on Safari and Chrome with flag enabled, Yes I am lazy to use old stuff )

Collapse
knighttechwork profile image
Randy Knight

This is really cool, thanks for sharing!