How to Implement Dark Mode with CSS Variables

Dark Mode has become increasingly popular for websites, offering a sleek and modern look that appeals to users. By switching the interface to darker colours, Dark Mode not only gives websites a stylish and contemporary feel but also provides practical benefits. It helps reduce eye strain, especially in low-light environments, making it easier for users to spend extended time on a site without discomfort. This feature can also improve battery life on devices with OLED screens, enhancing the overall user experience.

Implementing Dark Mode on your website can be a valuable addition that aligns with current design trends while catering to user preferences. 

Dark Mode and CSS Variables

CSS Variables, also known as custom properties, are a powerful tool in modern web design that allow developers to store reusable values, like colours, fonts, and other CSS attributes. By defining these variables once and reusing them throughout your stylesheet, you can manage and update your site’s design more efficiently. When it comes to implementing Dark Mode, CSS Variables are particularly effective because they allow you to switch themes seamlessly with minimal code changes.

Using CSS Variables for Dark Mode involves defining separate sets of variables for light and dark themes. These variables can control key design elements such as background colors, text colours, and button styles. By adjusting just a few variables, you can toggle the entire look of your site between light and dark modes, making CSS Variables an ideal solution for theme management.

One of the biggest advantages of using CSS Variables over other methods, like JavaScript, is performance. CSS operates directly within the browser’s rendering engine, which means changes happen quickly and without the additional processing overhead that JavaScript might incur. This enhances site performance but also provides a smoother and more immediate transition between themes.

Since all related properties are managed through a single set of variables, updating or tweaking the Dark Mode design is as simple as adjusting the variable values, without the need to hunt through your entire CSS file or JavaScript scripts. This centralized control reduces the risk of errors and makes your codebase cleaner and more organized.

Basic HTML and CSS Structure

To get started with implementing Dark Mode, you first need a basic HTML structure that will serve as the foundation for your light and dark themes. This setup will include a simple web page with a button to toggle Dark Mode, allowing users to switch between light and dark appearances effortlessly.

Here’s a simple HTML structure to demonstrate Dark Mode:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="/styles.css">
    <title>Dark Mode Example</title>
</head>
<body>
    <header>
        <h1>Welcome to Dark Mode</h1>
        <button id="toggle-dark-mode">Toggle Dark Mode</button>
    </header>
    <p>Dark Mode makes your site easier on the eyes and more stylish.</p>
</body>
</html>

This basic structure includes a header, a main heading, a toggle button, and a paragraph. The button is used to switch between light and dark modes.

Next, let’s set up the CSS with variables for both light and dark themes. The light mode will use default values, while the dark mode variables will be defined within a custom attribute (data-theme="dark") that can be toggled using JavaScript.

Here’s the basic CSS setup with CSS Variables for both themes:

/* Define default light mode variables */
:root {
    --background-color: #ffffff;
    --text-color: #000000;
    --button-background: #e0e0e0;
    --button-color: #000000;
}

/* Define dark mode variables under the dark theme attribute */
[data-theme="dark"] {
    --background-color: #1e1e1e;
    --text-color: #ffffff;
    --button-background: #333333;
    --button-color: #ffffff;
}

/* Apply the variables to style the page */
body {
    background-color: var(--background-color);
    color: var(--text-color);
    font-family: Arial, sans-serif;
    transition: background-color 0.3s, color 0.3s;
}

header {
    text-align: center;
    padding: 20px;
}

button {
    background-color: var(--button-background);
    color: var(--button-color);
    padding: 10px 20px;
    border: none;
    cursor: pointer;
    transition: background-color 0.3s, color 0.3s;
}

button:hover {
    opacity: 0.8;
}

In this CSS setup, the :root selector defines the default light mode variables for background colour, text colour, and button styles. The [data-theme="dark"] selector defines the dark mode variables, which are only applied when the data-theme="dark" attribute is present on the body.

Creating CSS Variables for Dark and Light Modes

CSS Variables make it easy to manage colour schemes for both light and dark modes by defining a set of reusable properties that control key elements like background and text colours. With this approach, you can quickly switch between light and dark themes by simply changing the values of these variables.

Defining CSS Variables for Light Mode

To start, you'll define the default variables for the light mode, which are set at the root level (:root). This ensures that these values are applied globally unless overridden.

Here’s a basic setup for light mode:

:root {
    --background-color: #ffffff; /* Light background color */
    --text-color: #000000; /* Dark text color for readability */
    --button-background: #e0e0e0; /* Light button background */
    --button-color: #000000; /* Dark text color on buttons */
}

These variables are defined at the root level and are used to style various parts of the page, such as the body, text, and buttons. The light mode uses a white background and dark text to ensure good readability, providing a clean and standard look that most users are familiar with.

Defining CSS Variables for Dark Mode

To enable Dark Mode, you define another set of variables within a custom attribute selector, such as [data-theme="dark"]. This allows you to easily switch the entire theme by toggling the attribute.

[data-theme="dark"] {
    --background-color: #1e1e1e; /* Dark background color for reduced glare */
    --text-color: #ffffff; /* Light text color for contrast */
    --button-background: #333333; /* Dark button background */
    --button-color: #ffffff; /* Light text color on buttons */
}

In this dark mode setup, the background colour is set to a dark shade to reduce glare and eye strain, while the text and button colours are adjusted to ensure readability against the dark background. This approach makes Dark Mode not just visually appealing but also functional for low-light environments.

How the Variables Work

Once these CSS Variables are defined, they can be used throughout your stylesheet by referencing their names, wrapped in var(). Here’s how these variables are applied in practice:

body {
    background-color: var(--background-color);
    color: var(--text-color);
    transition: background-color 0.3s, color 0.3s;
}

button {
    background-color: var(--button-background);
    color: var(--button-color);
    padding: 10px 20px;
    border: none;
    cursor: pointer;
    transition: background-color 0.3s, color 0.3s;
}

The var() function pulls the value of the CSS Variables and applies it to the respective styles. When the data-theme="dark" attribute is toggled on the body element, the dark mode variables automatically replace the light mode ones, allowing for a smooth and efficient transition between themes.

Adding the Dark Mode Toggle Functionality

To allow users to switch between light and dark modes, you'll need a small JavaScript function that toggles the theme when a button is clicked. 

The basic idea is to use JavaScript to toggle a custom attribute (data-theme="dark") on the body element. When this attribute is added, the CSS Variables defined under [data-theme="dark"] will be applied, switching the colours to Dark Mode. When the attribute is removed, the default light mode variables take over.

JavaScript Code to Toggle Dark Mode

Here's a simple script that adds or removes the data-theme="dark" attribute when a button is clicked.

// Select the toggle button element
const toggleButton = document.getElementById('toggle-dark-mode');

// Add an event listener to the button
toggleButton.addEventListener('click', () => {
    // Toggle the 'data-theme' attribute on the body
    if (document.body.getAttribute('data-theme') === 'dark') {
        document.body.removeAttribute('data-theme'); // Switch back to light mode
    } else {
        document.body.setAttribute('data-theme', 'dark'); // Activate dark mode
    }
});

Code Explanation

  • Selecting the Button: The script starts by selecting the toggle button using document.getElementById('toggle-dark-mode'). This button is the one users will click to switch between modes.
  • Adding an Event Listener: An event listener is added to the button that listens for the click event. When the button is clicked, the function inside the event listener is executed.
  • Toggling the Theme: The function checks if the body element has the data-theme="dark" attribute:
    • If the attribute is present, it means Dark Mode is active, so the script removes the attribute to revert to light mode.
    • If the attribute is not present, the script adds data-theme="dark" to activate Dark Mode.
  • Smooth Transitions: Since the CSS already includes a transition property, switching between themes will feel smooth and responsive, enhancing the user experience.

With the JavaScript code in place, you can now test the Dark Mode toggle on your website. Click the button to switch themes and see the colours change instantly. This setup not only makes your site visually dynamic but also gives users control over their browsing experience, aligning with the growing trend of personalization in web design.

Testing Your Dark Mode Implementation

Once you’ve set up Dark Mode using CSS Variables and added the toggle functionality, it’s essential to test your implementation across various browsers and devices. Proper testing ensures that your Dark Mode works smoothly for all users, maintains readability, and meets accessibility standards.

Testing Across Different Browsers and Devices

  1. Check Compatibility Across Browsers
    Test your Dark Mode feature in popular browsers like Chrome, Firefox, Safari, and Edge. Each browser may render styles slightly differently, so it’s crucial to verify that the colors, transitions, and toggle functionality work consistently.
  2. Test on Mobile Devices
    Dark Mode is particularly popular on mobile devices, where users often browse in low-light environments. Test your implementation on different devices, including Android and iOS smartphones and tablets, to ensure that the Dark Mode toggle functions correctly and the design remains responsive.
  3. Verify Performance on Slow Connections
    Simulate slower internet speeds or use performance testing tools to check how quickly your Dark Mode transitions occur. This helps ensure that your Dark Mode toggle remains smooth and doesn’t hinder user experience on lower bandwidths.

Accessibility in Dark Mode

  • Check Colour Contrast Ratios
    Accessibility is a key consideration when implementing Dark Mode. Use tools like the WebAIM Contrast Checker or browser developer tools to verify that the contrast ratio between background and text colours meets the recommended minimum of 4.5:1 for normal text and 3:1 for large text. Proper contrast ensures readability for users with visual impairments.
  • Test Keyboard Navigation
    Make sure that all interactive elements, such as the Dark Mode toggle button, are accessible via keyboard navigation. Check that focus states are clearly visible in both light and dark themes to ensure usability for keyboard users.
  • Review with Screen Readers
    Test your Dark Mode implementation with screen readers like NVDA, VoiceOver, or JAWS. Ensure that the toggle button is announced correctly and that the visual changes are appropriately conveyed to users relying on assistive technologies.
  • Evaluate User Feedback and Usability:
    If possible, gather feedback from real users or use tools like Hotjar to observe how people interact with the Dark Mode toggle on your site. User feedback can highlight any usability issues or improvements that can be made for a better experience.

Additional CSS Variables for Dark Mode

To create a truly polished Dark Mode experience, it's important to extend your use of CSS Variables beyond basic background and text colours. Customizing additional elements like links, buttons, headers, and other UI components enhances the overall user experience and ensures that every part of your design feels cohesive.

By defining additional CSS Variables, you can easily style more elements, such as links, borders, and buttons, to match your dark theme. 

Here are some additional CSS Variables you can define for a more comprehensive Dark Mode:

:root {
    --background-color: #ffffff;
    --text-color: #000000;
    --button-background: #e0e0e0;
    --button-color: #000000;
    --link-color: #1a0dab; /* Standard blue link color */
    --border-color: #cccccc; /* Light border for elements */
    --header-background: #f5f5f5; /* Light header background */
}

[data-theme="dark"] {
    --background-color: #1e1e1e;
    --text-color: #ffffff;
    --button-background: #333333;
    --button-color: #ffffff;
    --link-color: #4a90e2; /* Soft blue for links in dark mode */
    --border-color: #444444; /* Darker border for better contrast */
    --header-background: #2c2c2c; /* Dark header background */
}

These additional variables allow you to control the appearance of links, borders, and headers, providing a more refined look that aligns with Dark Mode principles. Below, we’ll see how to apply these variables across various elements.

Applying the Enhanced CSS Variables

Once you've defined the extra variables, you can incorporate them into your styles to create a unified theme:

body {
    background-color: var(--background-color);
    color: var(--text-color);
    transition: background-color 0.3s, color 0.3s;
}

header {
    background-color: var(--header-background);
    padding: 15px;
    text-align: center;
    transition: background-color 0.3s;
}

a {
    color: var(--link-color);
    text-decoration: none;
    transition: color 0.3s;
}

a:hover {
    text-decoration: underline;
}

button {
    background-color: var(--button-background);
    color: var(--button-color);
    padding: 10px 20px;
    border: 1px solid var(--border-color);
    cursor: pointer;
    transition: background-color 0.3s, color 0.3s, border-color 0.3s;
}

button:hover {
    opacity: 0.8;
}

This expanded set of CSS Variables helps maintain visual consistency and provides a better user experience by addressing various UI elements. The transition effects keep interactions smooth, enhancing the overall feel of the Dark Mode.

Best Practices for Dark Mode Design

Designing an effective Dark Mode involves more than just flipping colours from light to dark. To create a user-friendly and visually appealing experience, you need to ensure consistency and accessibility throughout your design. 

Maintain Consistent Design Elements

Consistency is key to a well-executed Dark Mode. Ensure that all elements, including text, buttons, icons, and backgrounds, are cohesively styled to avoid visual clutter or mismatched colours. Use CSS Variables consistently across your design to maintain harmony between light and dark themes. Avoid using bright or neon colours that can disrupt the dark aesthetic and cause visual fatigue.

Ensure Readable Contrast Ratios

Accessibility is crucial in Dark Mode design. It's important to provide sufficient contrast between text and background colours to make content readable for all users, including those with visual impairments. The Web Content Accessibility Guidelines (WCAG) recommend a minimum contrast ratio of 4.5:1 for body text and 3:1 for large text.

Consider Eye Comfort and Reduced Glare

Dark Mode should prioritize user comfort, especially in low-light conditions. Avoid pure black backgrounds (#000000) as they can create harsh contrasts, causing eye strain. Instead, opt for softer dark grays (#1e1e1e or #121212) that provide a more comfortable viewing experience and help reduce glare.

Design for Both Light and Dark Modes

Ensure that all UI elements are designed to function well in both light and dark themes. This includes icons, illustrations, and images that may need adjustments or alternative versions to suit Dark Mode. For instance, consider using lighter icons or outlines to ensure they are visible against dark backgrounds.

Test Your Design Across Devices

Dark Mode can render differently on various screens, such as OLED displays, which may have deeper blacks, or LCD screens, where colours might appear washed out. Test your Dark Mode implementation on multiple devices and screen types to ensure a consistent and high-quality experience.

Provide an Easy Toggle Option

Users should have control over switching between light and dark modes. Provide a clear and easily accessible toggle button, and remember to save user preferences using local storage so that the chosen mode persists on return visits.

Pay Attention to Colour Accents and Links

Accents and links in Dark Mode should stand out without being overly bright. Subdued colours work best in maintaining a cohesive design while ensuring interactive elements are easily recognizable. Make sure that link colours contrast well with both background and text colours for visibility and usability.

Keep Focus on Readability

Readability should be a top priority in Dark Mode. Choose legible font sizes and styles, and ensure that any focus indicators, like outlines on active elements, are still clearly visible against dark backgrounds. This is particularly important for accessibility and helps guide users through your site.

Need a Helping Hand with Your Project?

Whether you need continuous support through our Flexible Retainer Plans or a custom quote, we're dedicated to delivering services that align perfectly with your business goals.

Please enter your name

Please enter your email address

Contact by email or phone?

Please enter your company name.

Please enter your phone number

What is your deadline?

Please tell us a little about your project