DEV Community

Cover image for Create A Dark/Light Mode Switch with CSS Variables

Create A Dark/Light Mode Switch with CSS Variables

Ananya Neogi on April 10, 2019

Giving your users a way to customise the interface to their preference is a huge win for user experience. Here we are going to provide the user wit...
Collapse
 
ben profile image
Ben Halpern

Just how we do it with dev.to!

CSS variables are awesome.

Collapse
 
mittalyashu profile image
Yashu Mittal

Wait, what! There is dark theme for dev.to, nobody told me about that. 😂

Collapse
 
ben profile image
Ben Halpern

Dark mode is new, and it's fabulous (with a few kinks that still need to be worked out).

Thread Thread
 
mittalyashu profile image
Yashu Mittal

Oh! I see. How can I enable dark mode?

Thread Thread
 
ananyaneogi profile image
Ananya Neogi

Settings ➡ Misc. On that page you'll find it under "Style Customization"

Thread Thread
 
mittalyashu profile image
Yashu Mittal

Awesome, thanks. Looks cool.

Dark mode for dev.to

Collapse
 
ananyaneogi profile image
Ananya Neogi

Love the dark mode on dev.to! 🙂

Collapse
 
gevv profile image
gevv

@Ananya Neogi

Hi,

Dark mode does not not work link open new window (target="_blank" links)

is there a solution?

Thanks
Best regards

Collapse
 
zonayedpca profile image
Zonayed Ahmed

Where is bro? Just tell me where is it? I didn't know about it...

Collapse
 
mrcaspan profile image
MrCaspan • Edited

Hey just found a simple error in your CSS

.theme-switch-wrapper {
display: flex;
align-items: center;

em {
margin-left: 10px;
font-size: 1rem;
}
}

You have a nested selector here, this does not work in CSS only SCSS

so to fix it I just broke out the one selector to be on its own and not nested one!

.theme-switch-wrapper {
display: flex;
align-items: center;
}

.theme-switch-wrapper em {
margin-left: 10px;
font-size: 1rem;
}

Collapse
 
tomayac profile image
Thomas Steiner

CSS variables are fantastic for use cases like this. Here's a <dark-mode-toggle> that initially respects prefers-color-scheme and allows for manual overrides. Read more about it in this article.

Collapse
 
feldev profile image
Félix Paradis • Edited

Just added mine over at felixparadis.com :)

Quick note about accessibility though:
If you just display:none; your input, you're making it unaccessible through keyboard navigation.
Just hide it behind the label instead and everyone can toggle 🎉
Then add aria-label="Switch visual theme" to your input and blind users can know what's it about.

Collapse
 
ananyaneogi profile image
Ananya Neogi

Yes, this makes more sense. Thanks! 🙂
I'll update the demo.

Collapse
 
lizardbird profile image
Liz Jewell

Thanks for this! I haven't tried my own light/dark mode since I tried implementing it on my first bootcamp project a couple years ago. I technically got it to work, but the code was not this DRY as I made two individual buttons that would add/remove a "dark" or "light" class on the entire body element. 😂 Your solution is much better!

Collapse
 
bhupesh profile image
Bhupesh Varshney 👾

Nice post 👌👌 🤩
Gonna embed into my portfolio

Collapse
 
kiberusys profile image
Kiberu-sys

Thanks for this great post Ananya. I followed the instructions and managed to get the page up and running. But i am getting a console log Error: script5007 unable to get property 'addEventListener' for undefined or null source. Could someone please help me with a solution. Thanks.

Collapse
 
simoncoudeville profile image
Simon Coudeville

Very cool.

Have you thought about the prefers-color-scheme media feature? How could this be implemented in this script? You should check that too In my opinion. The toggle would have to automatically switch to the preferred color scheme.

Collapse
 
rolandixor profile image
Roland Taylor • Edited

I'm planning to experiment with something like this, but using CSS only (no javascript).

Collapse
 
zahir234 profile image
Zahir Stewart-Eaton

I keep trying to serve it via ng serve but instead i get the error "Property 'checked' does not exist on type 'Element" referring to "if (currentTheme) {
document.documentElement.setAttribute('data-theme', currentTheme);

if (currentTheme === 'dark') {
    toggleSwitch.checked = true;
}

}"

Collapse
 
rugk profile image
rugk

You won't believe it, but actually you can nowadays even take the operation system setting for the dark mode and apply/get that, so your users don't even need that toggle, or at least use the version they prefer, by default.
With CSS and JS…

Collapse
 
deschainxu profile image
DeschainX 𓅓

In my case, I would offer two toggle for users which are auto mode (system dark mode) and manual Light/Dark toggle, so users can choose whatever they prefer.

Collapse
 
nullcano profile image
Null

this doesn't work for me. console says 'toggleSwitch is null'

Collapse
 
mrcaspan profile image
MrCaspan

add the code after the switch in tags

Collapse
 
suryakumar007 profile image
Suryakumar Arumugam

Add the JS inside DOMContentLoaded method

Collapse
 
desi profile image
Desi

this is great and so helpful - thanks so much! I do have one question - in the js, where does "light" come from? unless I'm missing it, that's not defined in the CSS, is it?

Collapse
 
ananyaneogi profile image
Ananya Neogi

Hi Desi!
You're right, it's not defined anywhere.
If CSS doesn't find any specific styles related to light it will default back to the normal variables defined in :root.

Why I added it?
I added it so that we can use it while checking for the saved theme in localStorage further and add it to the root element. It will also be useful in cases where you might want to add some specific styles for light apart from the default styles.

I hope this helps 🙂

Collapse
 
desi profile image
Desi

Awesome, thanks so much! Explanation makes perfect sense.

Thread Thread
 
ananyaneogi profile image
Ananya Neogi

You're welcome 🙂

Collapse
 
noteray6421anymore profile image
Eray#6421

How we can set this for all pages?

Collapse
 
stealthmusic profile image
Jan Wedel

Great post. I would love to add a Dark theme to my website, but probably won’t have the time 😭. Bookmarked your article anyways 🤓

Collapse
 
_tearlach profile image
Charles

Thank you for taking the time to write this article, it has been a great help! Would you follow this for all types of run time theming too, or do you think there is a better way to have multiple themes which people can switch between?

Collapse
 
sagar profile image
Sagar

Super duper thanks for article.

Collapse
 
lucasgdb profile image
Lucas Bittencourt

Thanks! It will help me a lot. I've been using it wrong (but working), now you've cleared my mind. :)

Collapse
 
rhymes profile image
rhymes

Thank you Ananya! Great article, loved the tip about how to come up with a night theme :)

Collapse
 
mreed4 profile image
Matthew • Edited

Amazing work

Collapse
 
chicuong95 profile image
Cuong

Thanks Ananya, it's helpful for me

Collapse
 
victoreke profile image
Victor Eke

Thank you for this article, I implemented it on my portfolio. Here victoreke.netlify.app/

Collapse
 
singhofen profile image
Chase S.

Very Cool! Trying to figure out how to toggle between bg color & bg picture.

Collapse
 
roninjosue profile image
Reynaldo Josué Cano Bárcenas

Hello nice work, really help me a lot!!!

Collapse
 
gurupal profile image
Gurupal Singh

Hey, Nice article. I have one question .. what if i have two bootstrap based css files (theme-light.css and theme-dark.css) ?

Collapse
 
tapmeppe profile image
Patrick Meppe

Nice, simple and works well even while using .less .

Collapse
 
banzyme2 profile image
ENDEESA

Thank you so much!

Collapse
 
kriminalinc_11 profile image
Sergio Bernal • Edited

Great, thanks a lot!

I added an innerHTML to change the text as well:

Collapse
 
phantas0s profile image
Matthieu Cneude

A big thank! I was violently disabling dark-theme-CSS-sheet via JS for my blog, and it was creepy. This solution is way, way, way... way better!

I'm happy now.

Collapse
 
designboise profile image
Bryan Funk

How about images like the Logo in Header & Footer? How would you suggest making this happen?

Collapse
 
nullcano profile image
Null • Edited

add an image source changer in the functions or make the images a background image if you wanna change them with CSS

Collapse
 
umerrinayat profile image
Umer Inayat

I was exactly looking for something like this. Thanks

Collapse
 
thatafro profile image
Méhluli Hikwa

Really enjoyed this tutorial. I just had to include it in a codepen of my own. You can view it here - codepen.io/HikwaMehluli/full/jOPPEVx

Collapse
 
lucasandre profile image
Lucas André

AWESOME!!! <3

Collapse
 
gevv profile image
gevv

Hi,

Dark mode does not not work link open new window (target="_blank" links)

is there a solution?

Thanks
Best regards

Collapse
 
mrsid profile image
MrSid

I visited your website and just loved it.
Could you help me with websites like this please.
Which language have you used for Backend? Could you make a tutorial for a simple blog website please.

Collapse
 
tinaciousdesign profile image
Tina Holly

Amazing 🙌 Thank you! 🙏

Collapse
 
reythedev profile image
Rey van den Berg

Such a simple solution! Who needs a plugin when you can just use CSS variables!

Collapse
 
schoolmaxng profile image
Schoolmax.com.ng

Nice

Collapse
 
samus4145 profile image
Samus4145 • Edited

Is there any way to not have the background flash the "light" color before switching to "dark"? Little jarring to the user experience.

Collapse
 
olawanle_joel profile image
Joel Olawanle

Nice post, Thanks for writing 😁

Collapse
 
highcenburg profile image
Vicente G. Reyes

This isn't not working anymore?

Collapse
 
hkraji profile image
Haris Krajina

Good job, exactly what I was looking for. I made an account here just to say this. Thank you!

Collapse
 
prolover profile image
sithembiso

does is remember the mode once I refresh the page

Collapse
 
jonathan_pierce_51fafc9a5 profile image
Jonathan Pierce

This is probably a dumb question, but I'm confused on where I add the javascript?

Collapse
 
krankj profile image
Sudarshan K J

This was indeed a great article! Always wondered how to efficiently implement theming just using CSS Variables, and here it is! Good job!