简单记一记如何解决切换主题时的明暗闪烁
2 min
对于一个明暗双主题的 Astro 主题,在切换页面时经常会出现这样的情况。

这玩意的学名叫做 FOUC,也叫做 Flash of White。原因是浏览器在加载页面时,会先渲染 HTML。如果此时 JavaScript 还没来得及运行并给 html 标签加上 dark 类名,或者 CSS 还没加载完,浏览器就会默认使用白色背景,导致在暗色模式下看到一瞬间的白屏。
因为我的主题 Haku 也有这样的问题,那就来解决一下。
这是主题 global.css 中的部分代码。
@import url("https://fonts.loli.net/css2?family=Noto+Sans+SC:[email protected]");
@import url("https://fonts.loli.net/css2?family=SN+Pro:ital,wght@0,200..900;1,200..900&display=swap");
@import "tailwindcss";
@tailwind utilities;
@custom-variant dark (&:where(.dark, .dark *));
@layer base {
:root {
--haku-font: "SN Pro", "Noto Sans SC", sans-serif;
--color-border: #a8a8a8;
--color-readme: #44403b;
--color-readme-anchor: #155dfc;
--color-tag: #0a0a0a;
--color-tag-bg: #dfdfdf;
--color-tag-bg-hover: #a8a8a8;
--color-tag-title: #0a0a0a;
--color-tag-text: #202020;
font-family: var(--haku-font);
overflow-y: scroll;
}
html.dark {
--color-readme-anchor: #2b7fff;
--color-border: #3a3a3a;
--color-readme: #d6d3d1;
--color-tag: #dbdbdb;
--color-tag-bg: #2b2b2b;
--color-tag-bg-hover: #666666;
--color-tag-title: #d5d5d6;
--color-tag-text: #c5c5c5;
}
}首先要去掉 @import 指令,把它放在 <head> 标签中。因为外部 CSS 的优先级比较低,把 CDN 提供的 CSS 放在 HTML 文件里加载更好。
<head>
<!-- 一些内容 -->
<link
rel="stylesheet"
href="https://fonts.loli.net/css2?family=Noto+Sans+SC:[email protected]"
/>
<link
rel="stylesheet"
href="https://fonts.loli.net/css2?family=SN+Pro:ital,wght@0,200..900;1,200..900&display=swap"
/>
</head>然后要定义加载时的默认背景色,这就用 color-scheme 和 CSS 变量实现。
:root {
color-scheme: light;
background-color: var(--color-bg);
}
html.dark {
color-scheme: dark;
background-color: var(--color-bg);
}--color-bg 自己看着,调成背景色就行。
最后,也是最重要的,加一个 JS 阻塞脚本。在 <head> 标签里加一个脚本,从本地配置里面找有没有 theme 一项。
<script is:inline>
(function () {
const theme = localStorage.getItem("theme");
const systemDark = window.matchMedia(
"(prefers-color-scheme: dark)",
).matches;
if (theme === "dark" || (!theme && systemDark)) {
document.documentElement.classList.add("dark");
} else {
document.documentElement.classList.remove("dark");
}
})();
</script>这样就能根据读者本地环境自动适配,能够避免打开网页的时候被白光闪一下。