在切换到浅色模式时让背景颜色反转
我正在开发一个使用Catppuccin主题系统的网站。深色模式工作正常,但在浅色模式(Latte)下,背景图片的渲染始终有问题。
我的默认样式表使用一个 body::before 伪元素来显示一个SVG背景。
风格(主题变体)通过某些JS设置在 <html> 上的一个 data-flavor 属性,它在四种Catppuccin变体之间循环,Latte是其中的浅色版本。
在我的Latte样式表中,CSS变量设置得很好,能够工作。但我尝试为浅色模式覆盖背景伪元素的做法没有正确渲染。
到底哪里出错了?
最小可复现示例:
<!DOCTYPE html>
<html data-flavor="mocha">
<head>
<style>
/* Minimal Catppuccin-style variables */
html[data-flavor="mocha"] { --base: #1e1e2e; --text: #cdd6f4; }
html[data-flavor="latte"] { --base: #eff1f5; --text: #4c4f69; }
body {
margin: 0;
background: var(--base);
color: var(--text);
font-family: sans-serif;
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
}
/* Default (dark) background watermark */
body::before {
content: "";
position: fixed;
inset: 0;
background: url(https://upload.wikimedia.org/wikipedia/commons/0/00/Estradiol.svg) center / cover no-repeat;
filter: invert(86%) sepia(8%) saturate(900%) hue-rotate(190deg) brightness(105%);
opacity: 0.05;
pointer-events: none;
}
/* Attempted light-mode override — this is the broken part */
body::before[data-flavor="latte"] {
background: url(https://upload.wikimedia.org/wikipedia/commons/0/00/Estradiol.svg) center / cover no-repeat;
filter: invert(1);
}
</style>
</head>
<body>
<div>
<p>Background watermark should be <strong>light</strong> in Mocha, <strong>dark</strong> in Latte.</p>
<button onclick="document.documentElement.setAttribute('data-flavor','mocha')">Mocha (dark)</button>
<button onclick="document.documentElement.setAttribute('data-flavor','latte')">Latte (light)</button>
</div>
</body>
</html>
解决方案
正如评论中所建议的,
body::before[data-flavor="latte"]
在语法上是无效的;[attribute] 必须位于(可选的)元素与其伪内容之间:
body[data-flavor="latte"]::before
此外,你的测试 invert(1) 会使图像变白,实质上与近白色背景 #eff1f5 看起来没有区别。
如果你计划在任一明暗方案中只使用单一颜色主题,我建议不再使用数据属性,而是直接利用 color-scheme 的内联样式应用于 html。为调色板的明暗度明确对应一个 color-scheme 本身是有好处的:这会确保浏览器在渲染未经过样式处理的内容时表现更好(参见按钮和滚动条)。
此外,你还可以以一种方式利用自定义属性,让“变量”和它们的“应用”分离开来,这样主样式部分就不会分支;类似如下:
/* Minimal Catppuccin-style variables */
html {
--base: #1e1e2e;
--text: #cdd6f4;
--background: url(https://upload.wikimedia.org/wikipedia/commons/0/00/Estradiol.svg);
--background-filter: invert(86%) sepia(8%) saturate(900%) hue-rotate(190deg) brightness(105%);
}
html[style*="color-scheme: light;"] {
--base: #eff1f5;
--text: #4c4f69;
/* Keeping the "default" pic */
--background-filter: invert(30%);
}
body {
background-color: var(--base);
color: var(--text);
font-family: sans-serif;
&::before {
background: var(--background) center / cover no-repeat;
filter: var(--background-filter);
pointer-events: none;
content: "";
position: fixed;
inset: 0;
opacity: 0.05;
}
margin: 0;
display: flex;
align-items: center;
justify-content: center;
height: 110vh; /* for showing the scrollbar colour change */
}
<html style="color-scheme: dark;">
<div>
<p>Background watermark should be <strong>light</strong> in Mocha, <strong>dark</strong> in Latte.</p>
<button
onclick="document.documentElement.style.colorScheme='dark';">Mocha (dark)</button>
<button
onclick="document.documentElement.style.colorScheme='light';">Latte (light)</button>
</div>
你甚至可以通过省略“defaults”声明在“裸露的” html 上,让它更简洁,并把值直接放在具体应用的 var(…, fallback) 部分,例如:
background: var(--base, #1e1e2e);
但这感觉有点儿不干净……
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。