Merge pull request #359 from the-luap/fix/issue-358-theme-flash

fix(theme): pre-React bootstrap to kill white-flash on dark galleries (#358)
This commit is contained in:
Paul Nothaft
2026-05-02 00:07:04 +02:00
committed by GitHub
2 changed files with 52 additions and 0 deletions
+37
View File
@@ -5,6 +5,43 @@
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
<title>PicPeak - Photo Sharing Platform</title>
<script>
/*
* Pre-React theme bootstrap (#358).
*
* Without this, opening a dark-themed gallery flashes a white
* background between the HTML paint and React applying the gallery
* theme. We resolve a background colour synchronously from the URL
* slug (cached on previous visits) or the OS preference, and apply
* it to documentElement before any React render runs.
*
* Per-gallery cache is written by ThemeContext when the gallery
* theme actually loads, keyed by slug, so revisits never flash.
* First visits with no cache fall back to the OS preference.
*/
(function () {
try {
var m = location.pathname.match(/\/gallery\/([^\/?#]+)/);
var bg = null;
if (m && m[1]) {
bg = localStorage.getItem('gallery-theme-bg-' + decodeURIComponent(m[1]));
}
if (!bg && window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
bg = '#171717';
}
if (bg) {
var root = document.documentElement;
root.style.backgroundColor = bg;
root.style.setProperty('--color-background', bg);
}
} catch (e) { /* never block render on a cache miss */ }
})();
</script>
<style>
/* Smooth out the cache→API theme transition for the rare case where
the cached colour drifts from the freshly fetched theme (#358). */
html { transition: background-color 200ms ease; }
</style>
</head>
<body>
<div id="root"></div>
+15
View File
@@ -62,6 +62,21 @@ export const ThemeProvider: React.FC<ThemeProviderProps> = ({
if (themeConfig.backgroundColor) {
root.style.setProperty('--color-background', themeConfig.backgroundColor);
// Cache the resolved background by slug so the next visit can
// apply it from the inline bootstrap in index.html before React
// mounts (#358 — eliminates the white flash on dark-theme galleries).
try {
const m = window.location.pathname.match(/\/gallery\/([^/?#]+)/);
if (m && m[1]) {
localStorage.setItem(
`gallery-theme-bg-${decodeURIComponent(m[1])}`,
themeConfig.backgroundColor
);
}
} catch {
/* ignore — caching is best-effort */
}
}
if (themeConfig.textColor) {