豆豆友情提示:这是一个非官方 GitHub 代理镜像,主要用于网络测试或访问加速。请勿在此进行登录、注册或处理任何敏感信息。进行这些操作请务必访问官方网站 github.com。 Raw 内容也通过此代理提供。
Skip to content

Commit 501c20b

Browse files
fix: resolve flash of unstyled content (FOUC) in dark mode
1 parent 3d00fa8 commit 501c20b

File tree

3 files changed

+28
-1
lines changed

3 files changed

+28
-1
lines changed

src/generators/web/template.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono&family=Open+Sans:ital,wght@0,300..800;1,300..800" />
2020

2121
<!-- Apply theme before paint to avoid Flash of Unstyled Content -->
22-
<script>document.documentElement.setAttribute("data-theme", document.documentElement.style.colorScheme = localStorage.getItem("theme") || (matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"));</script>
22+
<script>${themeScript}</script>
2323
<script type="importmap">${importMap}</script>
2424
<script type="speculationrules">${speculationRules}</script>
2525
</head>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
'use strict';
2+
3+
/**
4+
* This script is designed to be inlined in the <head> of the HTML template.
5+
* It must execute BEFORE the body renders to prevent a Flash of Unstyled Content (FOUC).
6+
*/
7+
8+
export default `(function initializeTheme() {
9+
const THEME_STORAGE_KEY = 'theme';
10+
const THEME_DATA_ATTRIBUTE = 'data-theme';
11+
const DARK_QUERY = '(prefers-color-scheme: dark)';
12+
13+
const savedUserPreference = localStorage.getItem(THEME_STORAGE_KEY);
14+
const systemSupportsDarkMode = window.matchMedia(DARK_QUERY).matches;
15+
16+
const shouldApplyDark =
17+
savedUserPreference === 'dark' ||
18+
(savedUserPreference === 'system' && systemSupportsDarkMode) ||
19+
(!savedUserPreference && systemSupportsDarkMode);
20+
21+
const themeToApply = shouldApplyDark ? 'dark' : 'light';
22+
23+
document.documentElement.setAttribute(THEME_DATA_ATTRIBUTE, themeToApply);
24+
document.documentElement.style.colorScheme = themeToApply;
25+
})();`.trim();

src/generators/web/utils/processing.mjs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import getConfig from '../../../utils/configuration/index.mjs';
1313
import { populate } from '../../../utils/configuration/templates.mjs';
1414
import { minifyHTML } from '../../../utils/html-minifier.mjs';
1515
import { SPECULATION_RULES } from '../constants.mjs';
16+
import themeScript from '../ui/theme-script.mjs';
1617

1718
/**
1819
* Populates a template string by evaluating it as a JavaScript template literal,
@@ -137,6 +138,7 @@ export async function processJSXEntries(entries, template) {
137138
importMap: clientBundle.importMap?.replaceAll('/', root) ?? '',
138139
entrypoint: `${data.api}.js?${randomUUID()}`,
139140
speculationRules: SPECULATION_RULES,
141+
themeScript,
140142
root,
141143
metadata: data,
142144
config,

0 commit comments

Comments
 (0)