sass 的 lighten()/darken() 在深色模式下失效,因其仅机械调整明度而不感知背景明暗;应改用 mix()、预定义双色值或 contrast-color() 等方案。

深色模式下 lighten() 和 darken() 为什么失效
这两个函数在 Sass 中是基于 HSL 色相环做明度加减,但深色模式切换后,背景变暗、文字变亮,而 lighten($color, 10%) 对浅色和深色基底的效果完全相反:它会让深色更灰、浅色更亮,结果常导致文字在深色背景下对比度不足甚至看不见。
- 别用
lighten()/darken()做主题适配,它们不感知上下文明暗,只机械调明度 - 真正可靠的是
mix()或直接定义两套值,比如mix($white, $primary, 20%)在深色下更安全 - 如果必须用
lighten(),先判断当前主题:@if $theme == dark { ... },再选不同基准色
Sass 中用 prefers-color-scheme 媒体查询 + 变量控制是否可行
可行,但仅限于 CSS 变量(:root 中定义),Sass 编译时无法读取用户系统偏好,所以不能在 @if 里直接判断 prefers-color-scheme。你写的 Sass 是构建时跑的,不是运行时。
- 正确做法:用纯 CSS 媒体查询包裹自定义属性,再让 Sass 生成对应规则,例如:
:root { --text-primary: #333; }<br>@media (prefers-color-scheme: dark) {<br> :root { --text-primary: #eee; }<br>} - Sass 可以封装成 mixin:
@mixin color-mode($light, $dark) { --color: #{$light}; @media (prefers-color-scheme: dark) { --color: #{$dark}; } } - 注意:所有使用该变量的地方必须用
var(--color),不能在 Sass 中#{var(--color)}—— 这无效
如何用 Sass 函数自动推导深色模式下的文本/边框色
靠算法自动“适配”不如靠设计约束。真正能落地的是:给一组基础色(如 $brand-blue),按 WCAG 对比度要求,预计算出它在白底/黑底下的可读文字色(通常是黑白二选一),再用 Sass 函数封装逻辑。
- 推荐用
contrast-color()(来自sass:color模块):color.contrast-color($brand-blue)返回#000或#fff,取决于哪个对比度更高 - 但它只返回黑白,不够细;若需灰阶边框,可结合
grayscale()+lightness()判断:if lightness($color) > 50% { darken($color, 20%) } else { lighten($color, 20%) } - 重点:别试图让一个颜色“同时适配两种背景”,而是为每个语义色(
$text-body、$border-divider)分别定义深/浅两套值,Sass 生成对应 CSS 类或变量
构建时生成两套 CSS 的坑:@use 和作用域怎么管
用 @use 引入颜色模块时,变量默认私有,且不能跨 @media 块复用。想让深色/浅色样式共用同一组逻辑,得把颜色计算提前到顶层变量层,而不是塞进选择器里。
- 错误写法:
@use 'colors'; .card { background: colors.$bg; @media (prefers-color-scheme: dark) { background: darken(colors.$bg, 10%); } }——darken()仍会错 - 正确结构:在
_colors.scss里定义$bg-light: #fff; $bg-dark: #1a1a1a;,再用@each批量输出:@each $mode, $val in (light: $bg-light, dark: $bg-dark) { [data-theme='#{$mode}'] & { background: $val; } } - 注意:CSS 层叠优先级会变,
[data-theme='dark']必须确保在浅色规则之后,否则会被覆盖
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











