Block Dark Mode Extensions from Breaking Your Website
You spent weeks tuning your color palette. Every shade of blue, every muted gray, every hover state. Then someone visits your site with Dark Reader installed and it all looks like garbage. Wrong contrast, unreadable text, inverted logos.
If your site already has a proper dark mode, you don't need Dark Reader messing with it. Here's how to lock it out completely.
Why this matters
Extensions like Dark Reader, Night Eye, and Turn Off the Lights inject their own CSS to force dark themes on every page. They inject inline styles with !important, override your CSS variables, and add attributes to your DOM.
The problem: they can't tell your site already looks great in dark mode. They just steamroll everything.
The three part fix
You need to tell the extension three things:
- –Don't touch my HTML
- –Don't touch my styles
- –If you tried anyway, undo it
Each layer catches what the previous one missed.
Part one: the meta tag
The strongest signal. Dark Reader specifically checks for this and disables itself on your site if present.
Add this to your <head>:
<head>
<meta name="darkreader-lock" />
</head>In Next.js App Router, that lives in your src/app/layout.tsx:
export default function RootLayout({ children }) {
return (
<html lang="en">
<head>
<meta name="darkreader-lock" />
</head>
<body>{children}</body>
</html>
);
}For most users, this alone is enough. But some forks of Dark Reader ignore this tag, and other extensions never respected it in the first place. So we keep going.
Part two: HTML attributes
Add these to your <html> tag as a backup signal:
<html
lang="en"
className="darkreader-ignore"
data-darkreader-ignore=""
>Two different formats because different extension versions look for different things. Belt and suspenders.
Part three: CSS reset
If the extension somehow got through, it added inline styles to your elements. We can neutralize those by targeting the attributes it uses.
Add this to your global CSS:
[data-darkreader-inline-bgcolor],
[data-darkreader-inline-bgimage],
[data-darkreader-inline-color],
[data-darkreader-inline-border],
[data-darkreader-inline-border-bottom],
[data-darkreader-inline-border-left],
[data-darkreader-inline-border-right],
[data-darkreader-inline-border-top],
[data-darkreader-inline-boxshadow],
[data-darkreader-inline-fill],
[data-darkreader-inline-invert],
[data-darkreader-inline-outline],
[data-darkreader-inline-stroke] {
background-color: initial !important;
background-image: initial !important;
color: initial !important;
border-color: initial !important;
box-shadow: initial !important;
fill: initial !important;
outline-color: initial !important;
stroke: initial !important;
}
html[data-darkreader-mode],
html[data-darkreader-scheme] {
background-color: hsl(var(--background)) !important;
color: hsl(var(--foreground)) !important;
}The first block undoes any inline styles Dark Reader added to individual elements. The second block resets the root html element back to your own theme colors.
Part four: color scheme lock
There's one more thing. Browsers themselves adjust some default styles based on color-scheme. If your CSS says the site supports both light and dark, some extensions treat that as permission to override.
Lock it down in your CSS variables:
:root {
color-scheme: only light;
}
.dark {
color-scheme: only dark;
}The keyword only tells the browser this is the exact scheme and nothing else. No autoswitching, no extension interference.
Testing it works
- –Install Dark Reader in your browser
- –Visit your site
- –Nothing should change. Your colors stay yours.
- –Open DevTools and inspect the
<html>tag. Confirm your classes and attributes are present. - –Check your
<head>for the meta tag.
If Dark Reader is still overriding things, hard refresh with cache cleared. The extension caches per-domain decisions and may need to re-scan.
The full setup
Here's every piece together. In your src/app/layout.tsx:
<html
lang="en"
suppressHydrationWarning
className="darkreader-ignore"
data-darkreader-ignore=""
>
<head>
<meta name="darkreader-lock" />
</head>
<body>{children}</body>
</html>In your globals.css:
:root {
color-scheme: only light;
}
.dark {
color-scheme: only dark;
}
[data-darkreader-inline-bgcolor],
[data-darkreader-inline-bgimage],
[data-darkreader-inline-color],
[data-darkreader-inline-border],
[data-darkreader-inline-boxshadow] {
background-color: initial !important;
color: initial !important;
border-color: initial !important;
box-shadow: initial !important;
}
html[data-darkreader-mode],
html[data-darkreader-scheme] {
background-color: hsl(var(--background)) !important;
color: hsl(var(--foreground)) !important;
}That's it. Your carefully designed site stays exactly the way you built it.
When you shouldn't do this
If your site doesn't have a dark mode at all, don't do this. Dark Reader is helping your users read your content comfortably at night. Blocking it means they're stuck with a white flashbang at 2am.
Only lock it out when you already have a real dark theme that respects the user's system preference.
That's the honest tradeoff.