Dark Mode Without Flash of Wrong Theme
Flash of wrong theme (FOWT) happens when the page renders in the default palette before your JavaScript applies the user's preference. The fix is to set the theme before the body paints.
The Inline Script Pattern
Inject a synchronous <script> in <head> that runs before any CSS parses:
<head>
<script>
(function(){
var stored = localStorage.getItem('theme')
var preferred = matchMedia('(prefers-color-scheme: dark)').matches
? 'dark' : 'light'
document.documentElement.dataset.theme = stored || preferred
})()
</script>
<!-- rest of head -->
</head>
html
Why It Works
Browsers block rendering on synchronous scripts in <head>, so the data-theme attribute is set before any CSS with [data-theme="dark"] selectors is evaluated. No flash.
Don't Defer
Never use async or defer on this script — it must run synchronously to beat first paint.