fix: meta theme color flash issue

This commit is contained in:
radishzzz 2025-02-18 17:10:40 +00:00
parent 1040aff64c
commit b1777ed0ef
3 changed files with 60 additions and 52 deletions

View file

@ -26,7 +26,6 @@ function initScrollbar() {
} }
} }
document.addEventListener('theme-changed', initScrollbar)
document.addEventListener('astro:after-swap', initScrollbar) document.addEventListener('astro:after-swap', initScrollbar)
initScrollbar() initScrollbar()
</script> </script>

View file

@ -19,6 +19,22 @@ const { light: { background: lightMode }, dark: { background: darkMode } } = the
</button> </button>
<script define:vars={{ lightMode, darkMode }}> <script define:vars={{ lightMode, darkMode }}>
// Update theme
function updateTheme() {
// Toggle website theme
document.documentElement.classList.toggle('dark')
// Get current theme
const isDark = document.documentElement.classList.contains('dark')
// Update meta theme color
const metaThemeColor = document.querySelector('meta[name="theme-color"]')
if (metaThemeColor) {
metaThemeColor.setAttribute('content', isDark ? darkMode : lightMode)
}
// Update theme configuration in local storage
localStorage.setItem('theme', isDark ? 'dark' : 'light')
document.dispatchEvent(new Event('theme-changed'))
}
// Bind click event to the button // Bind click event to the button
function setupThemeToggle() { function setupThemeToggle() {
// Locate theme toggle button // Locate theme toggle button
@ -43,22 +59,6 @@ function setupThemeToggle() {
}) })
} }
// Update theme
function updateTheme() {
// Toggle website theme
document.documentElement.classList.toggle('dark')
// Get current theme
const isDark = document.documentElement.classList.contains('dark')
// Update meta theme color
const metaTheme = document.querySelector('meta[name="theme-color"]')
if (metaTheme) {
metaTheme.setAttribute('content', isDark ? darkMode : lightMode)
}
// Update theme configuration in local storage
localStorage.setItem('theme', isDark ? 'dark' : 'light')
document.dispatchEvent(new Event('theme-changed'))
}
// Initialize click event (on first load or page transition) // Initialize click event (on first load or page transition)
document.addEventListener('astro:after-swap', setupThemeToggle) document.addEventListener('astro:after-swap', setupThemeToggle)
setupThemeToggle() setupThemeToggle()

View file

@ -28,7 +28,7 @@ const { commentURL = '', imageHostURL = '', customGoogleAnalyticsURL = '', custo
<meta name="description" content={postDescription || description} /> <meta name="description" content={postDescription || description} />
<meta name="author" content={author} /> <meta name="author" content={author} />
<meta name="generator" content={Astro.generator} /> <meta name="generator" content={Astro.generator} />
<meta name="theme-color" content={lightMode} /> <meta name="theme-color" content="" />
<ClientRouter fallback="swap" /> <ClientRouter fallback="swap" />
<!-- Preload --> <!-- Preload -->
@ -79,55 +79,64 @@ const { commentURL = '', imageHostURL = '', customGoogleAnalyticsURL = '', custo
is:inline is:inline
define:vars={{ defaultMode: themeConfig.color.mode, lightMode, darkMode }} define:vars={{ defaultMode: themeConfig.color.mode, lightMode, darkMode }}
> >
// Initialize theme // Check if current theme is dark mode
function initTheme() { function isCurrentDark() {
const theme = (() => { const currentTheme = localStorage.getItem('theme')
const currentTheme = localStorage.getItem('theme') // Check local storage theme first
// First priority: theme from localStorage if (currentTheme)
if (currentTheme) return currentTheme === 'dark'
return currentTheme // Use configured default theme if available
// Second priority: user configured default theme if (defaultMode)
if (defaultMode) return defaultMode === 'dark'
return defaultMode // Finally follow system color scheme preference
// Last priority: follow system theme return window.matchMedia('(prefers-color-scheme: dark)').matches
return window.matchMedia('(prefers-color-scheme: dark)').matches }
? 'dark'
: 'light' // Update site theme
})() function updateThemeColor(isDark) {
// Update website theme
const isDark = theme === 'dark'
document.documentElement.classList.toggle('dark', isDark) document.documentElement.classList.toggle('dark', isDark)
// Update meta theme color }
// Update meta theme color
function updateMetaThemeColor(isDark) {
const metaTheme = document.querySelector('meta[name="theme-color"]') const metaTheme = document.querySelector('meta[name="theme-color"]')
if (metaTheme) { if (metaTheme) {
metaTheme.setAttribute('content', isDark ? darkMode : lightMode) metaTheme.setAttribute('content', isDark ? darkMode : lightMode)
} }
} }
// Update theme // 1.Update meta theme color before page transition to prevent flashing
function updateTheme() { document.addEventListener('astro:before-swap', () => {
// Read theme from localStorage const isDark = isCurrentDark()
const isDark = localStorage.getItem('theme') === 'dark' updateMetaThemeColor(isDark)
// Set theme directly instead of toggling })
document.documentElement.classList.toggle('dark', isDark)
const metaTheme = document.querySelector('meta[name="theme-color"]') // 2.Update site theme after page transition
if (metaTheme) { document.addEventListener('astro:after-swap', () => {
metaTheme.setAttribute('content', isDark ? darkMode : lightMode) const isDark = isCurrentDark()
} updateThemeColor(isDark)
})
// 3.Initialize theme on first load
const isDark = isCurrentDark()
updateThemeColor(isDark)
updateMetaThemeColor(isDark)
// Follow system theme changes automatically
function followSystemTheme() {
const isDark = isCurrentDark()
updateDocumentTheme(isDark)
updateMetaThemeColor(isDark)
document.dispatchEvent(new Event('theme-changed')) document.dispatchEvent(new Event('theme-changed'))
} }
// Listen to system theme changes in real-time // 4.Listen to system theme changes in real-time
window window
.matchMedia('(prefers-color-scheme: dark)') .matchMedia('(prefers-color-scheme: dark)')
.addEventListener('change', ({ matches: isDark }) => { .addEventListener('change', ({ matches: isDark }) => {
localStorage.setItem('theme', isDark ? 'dark' : 'light') localStorage.setItem('theme', isDark ? 'dark' : 'light')
updateTheme() followSystemTheme()
}) })
// Initialize theme (on first load or page transition)
document.addEventListener('astro:after-swap', initTheme)
initTheme()
</script> </script>
<!-- Google Analytics --> <!-- Google Analytics -->