Use !important inline styles for accent color to beat all CSS cascade

Both the index.html inline script and useTheme now use setProperty
with 'important' priority flag. This is the highest CSS cascade
priority and cannot be overridden by Vite's stylesheet injection,
@layer rules, or source order. Removes the <style> tag injection
approach which was being overridden.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Kyle 2026-03-12 20:17:04 +08:00
parent e7be762198
commit fce7405b14
2 changed files with 13 additions and 18 deletions

View File

@ -9,9 +9,9 @@
<meta name="mobile-web-app-capable" content="yes" /> <meta name="mobile-web-app-capable" content="yes" />
<title>UMBRA</title> <title>UMBRA</title>
<script> <script>
// Inject a <style> tag with accent color vars before React hydrates. // Apply accent color with !important inline styles — highest CSS priority.
// Uses a style element (not inline style attr) because Vite's CSS // Beats all stylesheet rules regardless of @layer, specificity, or source order.
// injection strips the html element's style attribute. // useTheme.ts updates these with !important when settings load from the API.
(function() { (function() {
var h = '187', s = '85.7%', l = '53.3%'; var h = '187', s = '85.7%', l = '53.3%';
try { try {
@ -23,10 +23,10 @@
if (p.l) l = p.l; if (p.l) l = p.l;
} }
} catch(e) {} } catch(e) {}
var el = document.createElement('style'); var d = document.documentElement.style;
el.id = 'umbra-accent'; d.setProperty('--accent-h', h, 'important');
el.textContent = ':root{--accent-h:' + h + ';--accent-s:' + s + ';--accent-l:' + l + '}'; d.setProperty('--accent-s', s, 'important');
document.head.appendChild(el); d.setProperty('--accent-l', l, 'important');
})(); })();
</script> </script>
<link rel="preconnect" href="https://fonts.googleapis.com" /> <link rel="preconnect" href="https://fonts.googleapis.com" />

View File

@ -16,8 +16,8 @@ export function useTheme() {
const { settings } = useSettings(); const { settings } = useSettings();
// Only apply accent color once settings have loaded from the API. // Only apply accent color once settings have loaded from the API.
// The <style id="umbra-accent"> tag in index.html handles initial paint. // The inline script in index.html handles initial paint from localStorage.
// Firing this effect with settings=undefined would overwrite the cache with cyan. // Both use !important inline styles — the highest CSS cascade priority.
useEffect(() => { useEffect(() => {
if (!settings) return; if (!settings) return;
@ -29,15 +29,10 @@ export function useTheme() {
const s = `${preset.s}%`; const s = `${preset.s}%`;
const l = `${preset.l}%`; const l = `${preset.l}%`;
// Update the injected <style> tag (survives Vite CSS injection, unlike inline styles) const d = document.documentElement.style;
const el = document.getElementById('umbra-accent'); d.setProperty('--accent-h', h, 'important');
if (el) { d.setProperty('--accent-s', s, 'important');
el.textContent = `:root{--accent-h:${h};--accent-s:${s};--accent-l:${l}}`; d.setProperty('--accent-l', l, 'important');
}
// Also set inline styles as a belt-and-suspenders fallback
document.documentElement.style.setProperty('--accent-h', h);
document.documentElement.style.setProperty('--accent-s', s);
document.documentElement.style.setProperty('--accent-l', l);
try { try {
localStorage.setItem('umbra-accent-color', JSON.stringify({ h, s, l })); localStorage.setItem('umbra-accent-color', JSON.stringify({ h, s, l }));