Easily Setup Dark/Light Mode in Your Apps

Liam Fernandez
Published: Nov 27th, 2023
Shedding Light on Web Design Trends: Light Mode & Dark Mode
In the ever-evolving world of web development, light mode and dark mode are the dynamic duo of design choices. These two modes flip the digital script by altering the color scheme of websites and apps, catering to both day and night owls.
Light mode, the classic and sun-soaked style, features bright backgrounds with dark text. It’s like a virtual sunbeam, illuminating the digital landscape. Conversely, dark mode is the mysterious rebel of the web, cloaking backgrounds in darkness and text in vibrant hues. Picture it as the Batcave of web design.
Why Offer Both?
User Preference: Remember the great pineapple on pizza debate? Users have equally passionate opinions about light and dark modes. Offering both ensures your website caters to diverse tastes. Some folks love the serene vibe of light mode, while others crave the cinematic allure of dark mode.
Accessibility: Accessibility isn’t just a buzzword; it’s a necessity. Dark mode, with its high-contrast text and backgrounds, can reduce eye strain for users with visual impairments or sensitivity to bright screens. Light mode, on the other hand, may be preferred by those with specific visual needs.
Battery Life: Dark mode can be a superhero for battery life on OLED screens. Fewer illuminated pixels mean less power consumption. Saving the planet, one dark pixel at a time!
Aesthetic Flexibility: Designers can flex their creative muscles by offering both modes. It’s like having two outfits for your website—one for a daytime picnic and one for a glamorous night on the town.
User Experience: Some users switch modes depending on their environment. Dark mode is great for nighttime browsing, while light mode might be the choice for a sunny afternoon coffee shop visit.
In conclusion, light mode and dark mode are the yin and yang of web design. They cater to diverse tastes, enhance accessibility, save battery life, and give designers creative freedom. Embracing both modes is like having a versatile wardrobe for your website—it’s not just trendy; it’s a smart and user-centric choice in modern web development.
Prerequisite
Purpose: This guide will show how to add dark mode / light mode functionality to any site.
Technologies used: All you need is vanilla JS and CSS.
Start Coding
The Button
Our first concern is how will the user interact with the dark/light mode system. This element will have to
- Communicate which mode the app is currently displaying
- Be interactive so that user can toggle between light & dark modes
The common sense choice is to use a <button>
html element. Set an onClick
function that will have some logic that tells the app to change outfits. Let’s start with a toggle button. I recommend this guide by Josh Collingsworth on how to build accessible toggle buttons.
- Toggle Button: Like a switch, it is a button that represents changing between two different states.
Your markup for the button will look different depending on the technology you are using to build your front-end. The minimum requirement is that your button can handle state changes. When the button is clicked, show different text/positioning/etc… to represent the mode it is currently in.
Here’s a simple toggle component in Svelte w/ Tailwind.
<script>
let darkModeEnabled = false;
</script>
<button
class="toggle"
on:click={() => {
darkModeEnabled = !darkModeEnabled;
}}
>
<div>
{#if !darkModeEnabled}
<span
class="outline outline-1 outline-white text-white px-2 py-1"
>
Dark Mode 🌙
</span>
{:else}
<span
class="outline outline-1 outline-white text-white px-2 py-1"
>
Light Mode ☀️
</span>
{/if}
</div>
</button>
The result is below, try clicking it.
Okay, the button is interactive, now how do we get the site’s outfit to change.
CSS Variables
CSS variables is how you define the outfits for when the app is in dark or light mode. They allow you to define and store values, such as colors, fonts, or sizes, that you can reuse throughout your stylesheet.
Think of CSS variables as customizable style properties. You define them once and then call upon them wherever needed. They are defined using the - - prefix.
For example:
:root {
--primary-color: #ff6347; /* Tomato */
--secondary-color: #5f9ea0; /* Cadet Blue */
}
Here, --primary-color
and --secondary-color
are our CSS variables, set to specific color values. The :root
selector is a common place to define these variables, as it represents the highest-level parent and makes the variables globally accessible.
Implementing Light and Dark Modes
In the context of light and dark modes, CSS variables shine by simplifying the switch. You can define a set of variables for each theme & to use these variables, you simply refer to them with the var()
function in your CSS properties
/* Light mode */
:root {
--background-color: #ffffff; /* White */
--text-color: #000000; /* Black */
}
/* Dark mode */
body.dark-mode {
--background-color: #363537; /* Dark Gray */
--text-color: #FAFAFA; /* Off White */
}
body {
background-color: var(--background-color);
color: var(--text-color);
}
In this setup, changing the mode is as simple as toggling a class on the body
element. When you add the dark-mode
class to the body, the variables switch to the values defined under body.dark-mode
.
Advantages of Using CSS Variables
- Consistency: By using variables, you maintain consistency across your design. Change the variable once, and it updates everywhere it’s used.
- Flexibility: It’s easy to create themes or adjust styles site-wide.
- Readability: Variables make your CSS more readable and easier to manage, especially in large projects.
Full Example
Now that we have the CSS variables and dark-mode
class set up, let’s demonstrate how we toggle that class on and off when the toggle is clicked.
Back to our ToggleExample
component, lets flesh out the onClick
function to change the class on the body element.
<script>
let darkModeEnabled = false;
</script>
<button
class="toggle"
on:click={() => {
if (!darkModeEnabled) {
document.body.classList.add("dark-mode");
} else {
document.body.classList.remove("dark-mode");
}
darkModeEnabled = !darkModeEnabled;
}}
>
<div>
{#if !darkModeEnabled}
<span
class="outline outline-1 outline-white text-white px-2 py-1"
>
Dark Mode 🌙
</span>
{:else}
<span
class="outline outline-1 outline-white text-white px-2 py-1"
>
Light Mode ☀️
</span>
{/if}
</div>
</button>
document.body.classList.add("dark-mode");
is the line of code that will change the values of the CSS variables.- If this isn’t working. Make sure in the main HTML/Layout/View of your app, that you
import "../app.css"
.
Auto-Detect User’s System Preference
A thoughtful touch for any modern website is to respect the user’s system preferences for light or dark mode. With the power of CSS media queries and a bit of JavaScript, we can easily detect these preferences and automatically set our website’s theme accordingly. Here’s how you can do it.
Using CSS Media Query for System Preferences
CSS Media Queries are the cornerstone of responsive design, and they come in handy for detecting user preferences for light or dark modes. The prefers-color-scheme
media query serves this exact purpose:
@media (prefers-color-scheme: dark) {
:root {
--background-color: #363537; /* Dark Gray */
--text-color: #FAFAFA; /* Off White */
}
}
@media (prefers-color-scheme: light) {
:root {
--background-color: #ffffff; /* White */
--text-color: #000000; /* Black */
}
}
/* Light mode */
:root {
--background-color: #ffffff; /* White */
--text-color: #000000; /* Black */
}
/* Dark mode */
body.dark-mode {
--background-color: #363537; /* Dark Gray */
--text-color: #FAFAFA; /* Off White */
}
body {
background-color: var(--background-color);
color: var(--text-color);
}
This CSS snippet checks the user’s system settings and applies the appropriate styles. However, to make your website dynamically switchable between light and dark modes, we need to add a bit of JavaScript magic.
JavaScript for Dynamic Theme Switching
Let’s use JavaScript to detect the preference and update the class on the body element:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.ico" />
<meta name="viewport" content="width=device-width" />
%sveltekit.head%
</head>
<body data-sveltekit-preload-data="hover">
<div style="display: contents">%sveltekit.body%</div>
</body>
<script>
window.addEventListener('load', () => {
const prefersDarkScheme = window.matchMedia("(prefers-color-scheme: dark)");
if (prefersDarkScheme) {
document.body.classList.add("dark-mode");
} else {
document.body.classList.remove("dark-mode");
}
});
</script>
</html>
This script runs when the window loads. It checks the user’s preference using window.matchMedia()
. If the user prefers dark mode, it adds a dark-mode
class to the body. If not, it ensures the class is removed.
Conclusion
With this setup, your website respects user preferences right off the bat, but also offers the flexibility to switch modes on the fly. It’s a small detail, but it goes a long way in enhancing the user experience on your site.