Dark Mode Implementation Tips: Add a Toggleable Dark Mode with CSS and JavaScript

Table of Contents
Big thanks to our contributors those make our blogs possible.

Our growing community of contributors bring their unique insights from around the world to power our blog. 

Introduction

In recent years, dark mode has evolved from a trendy visual option to an expected feature in modern web applications. Users increasingly prefer dark mode for its aesthetic appeal, reduced eye strain, and energy efficiency on OLED displays. As a developer, offering a toggleable dark mode is a smart move for both usability and accessibility.

The good news is that implementing dark mode is simpler than you might think. With CSS variables, JavaScript, and a bit of thoughtful design, you can offer a seamless light/dark mode toggle without relying on heavy frameworks.

In this post, we’ll walk through everything you need to know about dark mode implementation—from design tips and CSS techniques to JavaScript toggles and local storage persistence.

Why Offer Dark Mode?

Before diving into the code, let’s review the benefits of dark mode for both users and developers:

User Benefits:

  • Reduces eye strain in low-light environments
  • Enhances visual comfort for prolonged usage
  • Saves battery life on OLED and AMOLED screens
  • Offers a visually distinct and modern interface option

Developer Benefits:

  • Enhances user satisfaction and engagement
  • Aligns with system preferences (macOS, Windows, Android, iOS)
  • Improves accessibility for light-sensitive users

Core Concepts for Dark Mode Implementation

There are multiple ways to implement dark mode, but for flexibility and control, we’ll focus on a toggle-based solution using:

  • CSS custom properties (variables) for theme styling
  • JavaScript to toggle between themes
  • LocalStorage to persist user preference

This approach works with any frontend setup—whether you’re using vanilla HTML/CSS/JS or a framework like React, Vue, or Svelte.

Step 1: Define Theme Colors with CSS Variables

Use CSS variables to define light and dark theme colors at the :root level.

cssCopyEdit/* Light theme */
:root {
  --bg-color: #ffffff;
  --text-color: #121212;
  --primary-color: #0057ff;
}

/* Dark theme */
[data-theme="dark"] {
  --bg-color: #121212;
  --text-color: #ffffff;
  --primary-color: #3399ff;
}

Apply these variables in your CSS:

cssCopyEditbody {
  background-color: var(--bg-color);
  color: var(--text-color);
}

a {
  color: var(--primary-color);
}

This setup allows the entire theme to switch by simply toggling the data-theme attribute on the <html> or <body> tag.

Step 2: Create a Dark Mode Toggle in HTML

Add a toggle button or switch that users can interact with.

htmlCopyEdit<button id="theme-toggle">Toggle Dark Mode</button>

For accessibility, consider using aria-pressed or toggle roles for screen readers.

Step 3: Write JavaScript to Toggle Themes

Here’s a simple JavaScript snippet to toggle the data-theme attribute and save the user’s choice.

javascriptCopyEditconst toggleBtn = document.getElementById('theme-toggle');
const rootElement = document.documentElement;

const currentTheme = localStorage.getItem('theme');
if (currentTheme) {
  rootElement.setAttribute('data-theme', currentTheme);
}

toggleBtn.addEventListener('click', () => {
  let theme = rootElement.getAttribute('data-theme');
  if (theme === 'dark') {
    rootElement.setAttribute('data-theme', 'light');
    localStorage.setItem('theme', 'light');
  } else {
    rootElement.setAttribute('data-theme', 'dark');
    localStorage.setItem('theme', 'dark');
  }
});

Explanation:

  • Checks if a saved theme exists in localStorage
  • Applies it on page load
  • Toggles between light and dark on button click
  • Persists the new preference in localStorage

Step 4: Respect System Preferences (Optional Enhancement)

Many users set a system-wide preference for light or dark mode. You can detect this using the prefers-color-scheme media query.

cssCopyEdit@media (prefers-color-scheme: dark) {
  :root {
    --bg-color: #121212;
    --text-color: #ffffff;
    --primary-color: #3399ff;
  }
}

To use this in JavaScript as a default fallback:

javascriptCopyEditif (!currentTheme) {
  const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
  rootElement.setAttribute('data-theme', prefersDark ? 'dark' : 'light');
}

Step 5: Consider Transitions and Animations

To make theme switching feel smoother, use CSS transitions:

cssCopyEditbody {
  transition: background-color 0.3s ease, color 0.3s ease;
}

Be cautious with animations that affect visibility—dark mode should enhance comfort, not introduce motion distractions.

Step 6: Dark Mode Design Tips

When designing dark mode, avoid simply inverting colors. Instead, focus on:

  • Contrast ratios: Ensure text is readable on dark backgrounds
  • Saturated accent colors: Slightly desaturate for dark mode
  • Shadow adjustments: Use lighter shadows in dark environments
  • Consistent icon and image treatment: Use transparent backgrounds or theme-aware SVGs

Always test your design in both themes for usability and visual clarity.

Advanced Ideas and Considerations

  • Use prefers-color-scheme as default, but allow override
  • Integrate with frameworks like React or Vue using context or global state
  • Store preference in cookies for server-side rendering support
  • Add icons (e.g., sun/moon) to visually represent toggle states
  • Provide visual feedback when the theme changes (fading animation, etc.)

Conclusion

Implementing a toggleable dark mode is no longer just a nice-to-have feature—it’s quickly becoming a user expectation. With a combination of CSS variables, JavaScript, and local storage, you can build a robust and responsive dark mode that enhances user experience and accessibility.

By designing with contrast, clarity, and customization in mind, your site or app will not only look better—it will feel better to use, across all lighting environments.

Whether you’re building a marketing site, a web app, or an ecommerce platform, dark mode is a low-effort, high-impact improvement worth making.

Let's connect on TikTok

Join our newsletter to stay updated

Sydney Based Software Solutions Professional who is crafting exceptional systems and applications to solve a diverse range of problems for the past 10 years.

Share the Post

Related Posts