Skip to content

Commit 3f594df

Browse files
committed
fix: eliminate theme flicker on page refresh
- Add critical theme detection script in head.html - Apply theme immediately before CSS renders - Prevent Flash of Unstyled Content (FOUC) - Update JavaScript initialization to sync with pre-applied theme - Maintain theme persistence across page refreshes - Improve perceived performance and user experience
1 parent 690631e commit 3f594df

File tree

2 files changed

+45
-12
lines changed

2 files changed

+45
-12
lines changed

_includes/head.html

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,30 @@
7676

7777
{% include syntax-highlight.html %}
7878

79+
<!-- Critical Theme Detection Script - Prevents FOUC -->
80+
<script>
81+
// CRITICAL: This script must run IMMEDIATELY to prevent theme flicker
82+
(function() {
83+
try {
84+
// Get stored theme preference
85+
const storedTheme = localStorage.getItem('theme');
86+
const preferredTheme = storedTheme || 'dark';
87+
88+
// Apply theme immediately before any CSS renders
89+
document.documentElement.setAttribute('data-theme', preferredTheme);
90+
document.body.setAttribute('data-theme', preferredTheme);
91+
92+
// Store the detected theme for later JavaScript access
93+
window.initialTheme = preferredTheme;
94+
} catch (e) {
95+
// Fallback if localStorage is not available
96+
document.documentElement.setAttribute('data-theme', 'dark');
97+
document.body.setAttribute('data-theme', 'dark');
98+
window.initialTheme = 'dark';
99+
}
100+
})();
101+
</script>
102+
79103
</head>
80104

81105
<!-- HEAD End -->

_includes/js.html

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
<!-- Javascript Start -->
2+
<!-- Javascript Start - Theme Flicker Fix v1 -->
33

44
<!-- jQuery -->
55
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
@@ -27,7 +27,8 @@
2727
// State management
2828
this.isScrolled = false;
2929
this.isMobileMenuOpen = false;
30-
this.currentTheme = localStorage.getItem('theme') || 'dark';
30+
// Use pre-applied theme from critical script, fallback to localStorage or dark
31+
this.currentTheme = window.initialTheme || localStorage.getItem('theme') || 'dark';
3132

3233
// Performance optimization
3334
this.scrollTicking = false;
@@ -144,32 +145,40 @@
144145

145146
// 🌓 Theme Management
146147
initializeTheme() {
147-
this.setTheme(this.currentTheme, false);
148+
// Theme was already applied in head.html critical script
149+
// Just sync the toggle button state with the current theme
150+
this.syncThemeToggleState();
148151
}
149152

150153
toggleTheme() {
151154
const newTheme = this.currentTheme === 'dark' ? 'light' : 'dark';
152155
this.setTheme(newTheme, true);
153156
}
154157

155-
setTheme(theme, animate = true) {
156-
this.currentTheme = theme;
157-
158-
// Update DOM
159-
document.body.setAttribute('data-theme', theme);
160-
161-
// Update theme toggle button
158+
syncThemeToggleState() {
159+
// Only update the toggle button state - theme is already applied
162160
if (this.themeToggle) {
163-
this.themeToggle.setAttribute('aria-pressed', theme === 'light' ? 'true' : 'false');
161+
this.themeToggle.setAttribute('aria-pressed', this.currentTheme === 'light' ? 'true' : 'false');
164162

165163
// Update icon in the handle
166164
const toggleIcon = this.themeToggle.querySelector('.toggle-icon');
167165
if (toggleIcon) {
168-
toggleIcon.className = theme === 'light' ?
166+
toggleIcon.className = this.currentTheme === 'light' ?
169167
'toggle-icon fa fa-sun' :
170168
'toggle-icon fa fa-moon';
171169
}
172170
}
171+
}
172+
173+
setTheme(theme, animate = true) {
174+
this.currentTheme = theme;
175+
176+
// Update DOM (both html and body for maximum compatibility)
177+
document.documentElement.setAttribute('data-theme', theme);
178+
document.body.setAttribute('data-theme', theme);
179+
180+
// Update theme toggle button
181+
this.syncThemeToggleState();
173182

174183
// Store preference
175184
localStorage.setItem('theme', theme);

0 commit comments

Comments
 (0)