This blog post provides you a quick TL;DR for the best way to implement dark mode into your website.
Difficulty: Beginner
So, did I mean by the best?
- Browser support
- Performance
- Simplicity
In my opinion; though, there are supporting facts.
---- Let's jump right into it: ----
There are many ways to implement dark mode:
data-theme="theme"
-
@media(prefers-color-scheme)
link - Seperate CSS files (Don't walk this path please)
- classList toggle
I'm specifically promoting the data-theme
method. Click here if you can't bother about the others.
Why choose data-theme
?:
- amazing browser support.
- lightweight.
- clean code.
For other methods:
Use @media(prefers-color-scheme) if you're against legacy browsers. Here's why.@media(prefers-color-scheme)
Please, for the love of developers - don't use this method. Having seperate CSS files will negatively impact your webpage rendering speed. More CSS files means more Seperate CSS files
HTTP Requests
are sent to fetch your files, in which will consequently slow down the rendering process.
Well... if you're experienced, you probably heard of the classList toggle
classList.toggle
method. Yeah, it works exactly the same as data-theme
. Feel free to use it without guilt.
Code
Now that the explanation's done, let me show you an example.
Codepen Example
HTML
I used pug for my HTML, but incase you don't know what's going on:
<div id="container">
<div id="theme-text">Hi, I'm light theme</div>
<div id="theme-switch">Click me to change theme</div>
</div>
CSS
I used SCSS as my preprocessor; worry not, I didn't put any SCSS stuff in here. To access the attributes associated with the element, use square brackets. In this case, data-theme="dark"
is to be accessed when its value is "dark".
:root{
--color-bg:#faf7f0;
--color-font:#363636;
}
body[data-theme="dark"]{
--color-bg: #282930;
--color-font: #b1b3bd;
}
body{
background-color:var(--color-bg);
color:var(--color-font);
font-size:1.5rem;
transition:.2s background-color,.2s color;
}
#container{
display:flex;
align-items: center;
justify-content: center;
flex-direction:column;
margin-top:35vh;
}
#theme-switch{
border:1px var(--color-font) solid;
margin-top:1rem;
padding:1rem;
border-radius:1rem;
user-select:none;
cursor:pointer;
}
You will need to use variables if you want it clean. You can create variables to store any value, with the syntax:
--+name:value
Make sure you create them in :root
to prevent scope problems.
JS
This is vanilla javascript. :) Noticed how I used the localStorage.setItem
method. This works only for the client browser. If you want it to work for the same user on any client, check out SSP.
const themeText = document.getElementById("theme-text")
const themeSwitch = document.getElementById("theme-switch")
if (window.localStorage.getItem("theme") === "dark"){
document.body.dataset.theme = "dark";
themeText.innerHTML = "Hi, I'm dark theme";
}
themeSwitch.addEventListener("click",function(){
if(document.body.dataset.theme !== "dark"){
document.body.dataset.theme = "dark"
themeText.innerHTML = "Hi, I'm dark theme"
window.localStorage.setItem("theme","dark")
}else{
document.body.dataset.theme = "light"
themeText.innerHTML = "Hi, I'm light theme"
window.localStorage.setItem("theme","light")
}
})
The data-theme
attribute in body
is accessed with dataset.theme
in JS.
---------End---------
There you go! This is how you can easily add dark mode without any regrets. Though, remember that this is only a small part of the module - at least let me guide you for the design.
<3
Top comments (6)
The demo is not working on mobile
I'm so sorry! May I know which browser are you using?
Sorry, I should have mentioned it. Im using Brave on Android. But just tested with Chrome on Android and it works fine... Maybe it's just my browser?
I think that might be the case! Though brave on iOS works perfectly... Unfortunately I can't find a way to find support for other browsers... That was my bad!
forget about the 1 line js code bla bla bla to turn website into dark mode. using css variables is the best way 👍
Its good to squeeze in every drop of performance :)