
How to Make an Animated Day and Night Toggle Switch
Providing an option for your users to toggle between a dark and light theme can be a great way to let them:
- Reduce the brightness of your site at night
- Save battery power when low
- Or just provide a different version of your site for their preference
We will look at how you can create an animated toggle button with only CSS. We will also be looking at how you can use CSS variables to define different color schemes. And by the end of this tutorial, you will be able to build a light switcher, like the one below:


Setting Things Up
Create anĀ index.html
Ā file at the root of your project and fill it with the following:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Day & Night Toggle Switch</title>
<link rel="stylesheet" href="colors.css" />
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<span class="toggle"></span>
<div class="wrapper">
<h1>Day & Night</h1>
<h2>Toggle Switch</h2>
<p>Created with CSS</p>
<span>Using <b>CSS</b> variables</span>
</div>
<script src="toggle.js"></script>
</body>
</html>
Weāre going to have three different resources:
colors.css
Ā will hold all the color definitionsstyles.css
Ā will hold the styles for theĀ.toggle
Ā as well as theĀ.wrapper
toggle.js
Ā will hold a click event listener for toggling classes
Letās go over each and see what we need to add for them. At first, we want to create the toggle.
Creating The Toggle
Open up yourĀ styles.css
Ā and define the following styles for theĀ .toggle
:
.toggle {
position: absolute;
cursor: pointer;
top: 20px;
right: 25px;
font-size: 150%;
}
.toggle:before {
content: 'āļø';
}
.toggle.active:before {
content: 'š';
}
I have to mention two important things here. First, you should setĀ cursor
Ā toĀ pointer
Ā to provide visual feedback to the user that the element can be interacted with. Secondly, we want to change the icon āĀ which is in the content of theĀ before
Ā pseudo-elementĀ ā based on anĀ .active
Ā class.

Of course, we donāt want to toggle the class through DevTools, so letās add the event listener in JavaScript.
Adding the Event Listener
For this to work, we need the following function attached to theĀ .toggle
Ā element.
document.querySelector('.toggle').addEventListener('click', function() {
this.classList.toggle('active');
});
At this point, we are able to toggle the icon on and off. To spice things up, letās also add some animation.

Adding the Scaling Animation
The animation will work in the following way: We scale the icon down to 0. When it hits 0, the icon is essentially invisible. This is when we need to toggle theĀ .active
Ā class to change the icon. Then we scale the icon back to its original size.

To achieve this, add the following to yourĀ style.css
Ā file:
.toggle.animate {
animation: animate .3s cubic-bezier(0.4, 0.0, 0.2, 1);
}
@keyframes animate {
0% { transform: scale(1); }
50% { transform: scale(0); }
100% { transform: scale(1); }
}
We will animate the icon in 300ms to make the animation fast. To handle this through JavaScript, we will also need to modify our event listener a bit.
document.querySelector('.toggle').addEventListener('click', function() {
+ this.classList.add('animate');
+ setTimeout(() => {
this.classList.toggle('active');
+ }, 150);
+ setTimeout(() => this.classList.remove('animate'), 300);
});
First, we need to add the animate class to start the animation. At the half of the animation āĀ which is set to 300ms inĀ styles.css
, so we need to use 150 hereĀ ā we toggle theĀ .active
Ā class. At the end of the animation, we can remove theĀ .animate
Ā class.


Adding The Ripple Effect
To make the background transition feel like a wave, we can use a CSS trick instead of changing theĀ background-color
Ā property. We will animate theĀ box-shadow
Ā instead. For this to work, we need a new element. Add the following line to yourĀ index.html
Ā file:
<!DOCTYPE html>
<html lang="en">
<head>
...
</head>
<body>
<span class="toggle"></span>
<span class="wave"></span>
...
</body>
</html>
Since we are already doing some animation on theĀ .toggle
Ā element, we donāt want to animate itsĀ box-shadow
, otherwise, we would get weird effects. That is why we need to use a separate element. Letās define the styles associated with the it.
.wave {
position: absolute;
top: 35px;
right: 40px;
border-radius: 100%;
width: 2px;
height: 2px;
display: block;
z-index: -1;
box-shadow: 0 0 0 0 #212121;
transition: box-shadow .3s cubic-bezier(0.4, 0.0, 0.2, 1);
}
.wave.active {
background: #212121;
box-shadow: 0 0 0 9999px #212121;
}
Some important things I would like to point out:
- TheĀ
.wave
Ā needs to be positioned exactly in the middle of the icon, so it starts growing from its inside. - ItsĀ
border-radius
Ā needs to be set to 100% to be circular. - Why theĀ
2px
Ā for width and height? This is the smallest size on whichĀborder-radius
Ā works. - Youāll also need to setĀ
z-index
Ā to -1 to make sure it doesnāt cover other elements on the page. - I set theĀ
background-color
Ā purposefully to black on theĀ.active
Ā state to prevent a white dot showing in place of the icon, when itās invisible.

If we start changing the size of theĀ box-shadow
, we can see that the background slowly turns into darkness. Letās also update the event listener in JavaScript:
document.querySelector('.toggle').addEventListener('click', function() {
this.classList.add('animate');
setTimeout(() => {
this.classList.toggle('active');
document.querySelector('.wave').classList.toggle('active');
}, 150);
setTimeout(() => this.classList.remove('animate'), 300);
});

Adding Color Definitions
All thatās left to do is to add the color definitions so we have different styles for different themes. Open up yourĀ colors.css
Ā file and fill it with the following content:
html {
--background: #212121;
--box-shadow: #000;
--text: #FFF;
--text-faded: #CCC;
--badge-background: #162F48;
--badge-color: #0B81D0;
}
.theme-dark {
--background: #FFF;
--box-shadow: #CCC;
--text: #212121;
--text-faded: #333;
--badge-background: #FFDA44;
--badge-color: #d35400;
}
As you can see, we donāt have anything, besides the colors. All we are doing here is rewriting the CSS variables for different themes. Again, we want to toggle a class, but this time, on the HTML element itself.
document.querySelector('.toggle').addEventListener('click', function() {
this.classList.add('animate');
setTimeout(() => {
this.classList.toggle('active');
document.querySelector('.wave').classList.toggle('active');
document.documentElement.classList.toggle('theme-dark');
}, 150);
setTimeout(() => this.classList.remove('animate'), 300);
});
This is the last thing to add in theĀ .toggle
Ā event listener. So how would you use these variables inside CSS? Instead of hard-coding colors, you can use theĀ var
Ā function to retrieve the values from the defined colors.
.wrapper {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
padding: 20px;
background: var(--background);
color: var(--text);
border-radius: 5px;
box-shadow: 0 3px 0 0 var(--box-shadow);
transition: all .3s cubic-bezier(0.4, 0.0, 0.2, 1);
}
Make sure you add aĀ transition
Ā property to smoothly animate the colors. All thatās left to do is to test everything out.


Summary
In roughly 10 lines of JavaScript code, you are able to create a day-night toggle switch to help your users in various ways. Itās easy to implement and highly customizable. With the help of CSS variables, you can also create multiple themes by simply adding another class with another set of color schemes.
If you would like to experiment with the finished project, you canĀ clone it from GitHub. Thank you for taking the time to read this article. Happy coding!

Unlimited access to hundred of tutorials
Access to exclusive interactive lessons
Remove ads to learn without distractions