VOOZH about

URL: https://dev.to/weatherclockdash/dark-mode-in-firefox-extensions-respecting-system-preferences-1iok

⇱ Dark Mode in Firefox Extensions: Respecting System Preferences - DEV Community


Dark Mode in Firefox Extensions: Respecting System Preferences

Firefox users who prefer dark mode shouldn't have to manually toggle it in every extension. Here's how to automatically respect the system preference.

The CSS Media Query

/* Default: light mode */
:root {
 --bg: #ffffff;
 --text: #1a1a1a;
 --card-bg: #f5f5f5;
 --border: #e0e0e0;
}

/* Auto dark mode from system */
@media (prefers-color-scheme: dark) {
 :root {
 --bg: #1a1a2e;
 --text: #e0e0e0;
 --card-bg: #16213e;
 --border: #2d3561;
 }
}

Using CSS custom properties makes this effortless — one block of overrides handles the whole page.

JavaScript Detection

For dynamic behavior based on the current theme:

const isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;

// Listen for changes (user switches system theme)
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => {
 const newScheme = e.matches ? 'dark' : 'light';
 applyTheme(newScheme);
});

Three-Way Toggle: Auto / Light / Dark

For maximum user control, offer three options:

// Possible values: 'auto', 'light', 'dark'
const THEME_KEY = 'theme';

async function getCurrentTheme() {
 const { theme } = await browser.storage.sync.get({ theme: 'auto' });
 return theme;
}

function getEffectiveTheme(theme) {
 if (theme === 'auto') {
 return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
 }
 return theme;
}

async function applyTheme() {
 const stored = await getCurrentTheme();
 const effective = getEffectiveTheme(stored);
 document.documentElement.setAttribute('data-theme', effective);
}

Then in CSS:

[data-theme="light"] {
 --bg: #ffffff;
 --text: #1a1a1a;
}

[data-theme="dark"] {
 --bg: #1a1a2e;
 --text: #e0e0e0;
}

This is cleaner than combining CSS media queries with JS overrides.

Animating Theme Changes

Soft transitions prevent jarring flashes:

:root {
 transition: background-color 0.2s ease, color 0.2s ease;
}

.card {
 transition: background-color 0.2s ease, border-color 0.2s ease;
}

But disable transitions on initial page load to avoid FOUC:

// Apply theme before DOMContentLoaded to prevent flash
async function initTheme() {
 const stored = await getCurrentTheme();
 const effective = getEffectiveTheme(stored);
 // Apply without transition on first load
 document.documentElement.style.transition = 'none';
 document.documentElement.setAttribute('data-theme', effective);
 // Re-enable transitions after a tick
 requestAnimationFrame(() => {
 document.documentElement.style.transition = '';
 });
}

// Call immediately, before parsing the rest of the DOM
initTheme();

Theme Switcher UI

<div class="theme-toggle" role="group" aria-label="Theme">
 <button data-theme="light" title="Light mode">☀️</button>
 <button data-theme="auto" title="Auto (system)" class="active">🌓</button>
 <button data-theme="dark" title="Dark mode">🌙</button>
</div>
document.querySelectorAll('[data-theme]').forEach(btn => {
 btn.addEventListener('click', async () => {
 const theme = btn.dataset.theme;
 await browser.storage.sync.set({ theme });
 applyTheme();
 // Update active state
 document.querySelectorAll('[data-theme]').forEach(b => b.classList.remove('active'));
 btn.classList.add('active');
 });
});

Colors to Get Right in Dark Mode

Common mistakes when designing dark mode:

  • Don't use pure black (#000000) — it looks harsh. Use #1a1a2e or similar.
  • Reduce saturation of accent colors — bright colors look garish on dark backgrounds
  • Adjust shadow opacity — box shadows need lower opacity on dark backgrounds
  • Check icon colors — SVGs with fill: currentColor work, but PNG icons may need separate dark versions
/* Shadows that work in both modes */
:root {
 --shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

[data-theme="dark"] {
 --shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
}

Testing Dark Mode

In Firefox DevTools, you can simulate dark mode without changing your system settings:

  1. Open DevTools
  2. Click the Responsive Design Mode icon (or Ctrl+Shift+M)
  3. In the toolbar, find the Color scheme toggle

Or toggle via DevTools console:

// Simulate dark mode in DevTools
// DevTools → Console → type:
window.matchMedia('(prefers-color-scheme: dark)').matches
// Returns true/false

Firefox also has a media feature emulation panel in the DevTools inspector.


Weather & Clock Dashboard supports auto/light/dark mode, following your system preference out of the box. Free, MIT licensed.