DEV Community

loading...
Cover image for Make Light/Dark mode Toggle for your Website using CSS

Make Light/Dark mode Toggle for your Website using CSS

Sarah Thompson
Just a lady surfing the web
Updated on ・4 min read

Having light and Dark mode on web or desktop applications is a great feature to not only make the user's eyes happier, but to show off some fun and fancy css skills. It gives off an extra level of polish for your personal site if you're using it in a portfolio for a new job. I recently did it on my personal website - but instead of traditional light and dark mode, I changed the colors and themes to be "Light Academia Aesthetic" and "Dark academia Aesthetic".

Pick Your Colors

First thing first pick your two color palletes for light mode and dark mode. I like to use coolors.co to help select colors to get ideas on what to pick.

image

Now with your hex colors selected we are going to set them as variables in your top .css file. Setting them as variables and then using those variables to assign to individual instances that are using the colors makes for cleaner code, better consistency, and easier updates should you want to change a color.

:root {
  /** sunny side **/
  --light-background: #b87e54;
  --light-olive: #4d4828;
  --light-blue: #99c1c3;
  --light-purple: #67597a;
  --light-yellow: #e0cd7e;
  /** dark side **/
  --dark-background: #283618;
  --dark-darkblue: #001d3d;
  --dark-blue: #003566;
  --dark-darkestblue: #000814;
  --dark-mustard: #664e00;
}
Enter fullscreen mode Exit fullscreen mode

These colors can then be easily accessed by calling the variable name you assigned the hex color to background-color: var(--dark-background); .

Build Your Toggle

For the toggle we are going to build off of an input HTML element. This input and its associated label will be turned into something that looks like a toggle with css, but will continue to function the same as a checked, or unchecked, input element. We will be leaning heavily on the ::before and ::after pseudo-elements to get it done.

<input type="checkbox" id="toggle" class="mostHigh toggle--checkbox" />
<label for="toggle" class="toggle--label mostHigh">
</label>
Enter fullscreen mode Exit fullscreen mode

We want to hide .toggle--checkbox with display: none so that the original checkbox isn't visible and then create the toggle outline with .toggle--label.

.toggle--label {
  width: 80px;
  height: 40px;
  background: var(--blue-color);
  border-radius: 100px;
  border: 5px solid var(--blue-border);
  display: flex;
}
Enter fullscreen mode Exit fullscreen mode

We will be using the pseudo-element ::before to create the switch portion that will toggle back and forth.

.toggle--label:before {
  animation-name: reverse;
  animation-duration: 350ms;
  animation-fill-mode: forwards;
  transition: all 350ms ease-in;
  content: "";
  width: 30px;
  height: 30px;
  border: 5px solid var(--yellow-border);
  top: 0px;
  left: 4px;
  position: absolute;
  border-radius: 82px;
  background: var(--yellow-background);
}
Enter fullscreen mode Exit fullscreen mode

Now we will be using css pseudo-class selector `:checked' to determine inside the css whether or not the toggle has been clicked on or off. This is very convenient, it prevents having to update the DOM with JavaScript or do conditional rendering.

CSS selectors might have more than one simple selectors and between them we include a combinator. In this toggle we are using an adjacent sibling selector + to select the sibling of the class .toggle--checkbox (the input) which is .toggle--label (the label). Other combinators for simple selectors are descendant selector (space), a child selector > and general sibling selector ~.

It works in a similar way as :hover does, that when that class is checked then the css will update the sibling selectors code. The sibling qualifier is based on the HTML elements to which the classes are assigned.
`

.toggle--checkbox:checked + .toggle--label {
  background: var(--indigo-color);
  border-color: var(--indigo-border);
}

.toggle--checkbox:checked + .toggle--label:before {
  background: var(--white);
  border-color: var(--gray-border);
  animation-name: switch;
  animation-duration: 350ms;
  animation-fill-mode: forwards;
}
Enter fullscreen mode Exit fullscreen mode


`

Animate the Toggle

Right now the toggle will change colors and move around, and make it visually appear to be toggling. We can do this in css too. We will be using Keyframes for this. Having the keyframes created then assigned to the animation-name attribute that is on .toggle--label:before. We are using the keyframes to create visual motion and make the circle toggle move from the left side of the toggle switch to the right - and then back.
`

@keyframes switch {
  0% {
    left: 4px;
  }
  60% {
    left: 20px;
    width: 50px;
  }
  100% {
    left: 40px;
    width: 30px;
  }
}
@keyframes reverse {
  0% {
    left: 24px;
    width: 42px;
  }
  60% {
    left: 20px;
    width: 50px;
  }
  100% {
    left: 4px;
  }
}
Enter fullscreen mode Exit fullscreen mode


`

Have the Toggle Effect the Site with Day/Night Mode

To push day/night mode to the rest of your site we are going to be using the same process that we used for the .toggle--label. We want to make sure that the toggle itself is near the top level so that the header and the main part of the site can be sibling elements to grab on to.

`

<Header />
<Toggle />
<Main />
Enter fullscreen mode Exit fullscreen mode


`

In the way you will be watching to see if the toggle input gets checked, and if so updating the initial css to the toggled css.
`

.header {
  background-color: var(--light-background);
  color: var(--light-olive);
}

.toggle--checkbox:checked ~ .head {
  background-color: var(--dark-background);
  color: var(--white);
}
Enter fullscreen mode Exit fullscreen mode


`

Have fun toggling your different colors around!

Discussion (8)

Collapse
lukeshiru profile image
LUKESHIRU • Edited

Ideally you could make the colors depend on the user's OS preference:

:root {
  --background: #FFF;
  --foreground: #000;
}

@media (prefers-color-scheme: dark) {
  :root {
    --background: #000;
    --foreground: #FFF;
  }
}
Enter fullscreen mode Exit fullscreen mode
Collapse
barelyhuman profile image
Reaper

Or a shameless plug: themer.reaper.im/

Collapse
mayankav profile image
mayankav

Well compiled Sarah. It’d have been even better had you added a link to some live demo. You mentioned you used it in your website. Anyway, good content. ;)

Collapse
codingsafari profile image
Nico Braun

Coincidentally I have pretty much created what has been shown here 2 days ago in codepen.

Collapse
hugekontrast profile image
Ashish Khare😎

Antaryami guru ji!

Collapse
mayankav profile image
mayankav

Sharp 😎

Collapse
samael3 profile image
samael3

Bro you blowed my mind off..you create dark mode toggle without JavaScript....thank you very much