transition 必须写在基础选择器中,因为浏览器只对明确值间的属性做插值动画;若仅放在 .dark-theme 中,初始无过渡声明会导致切换时瞬间跳变闪屏。

transition 必须写在基础选择器里,不能只放在 .dark-theme 中
闪屏的根本原因是:浏览器只对「从一个明确值变到另一个明确值」的属性做插值动画。如果 transition 只写在 .dark-theme 类里,那默认状态下没有过渡声明,切换 class 时会瞬间跳变——你看到的就是颜色“啪”一下闪过去。
正确做法是把 transition 声明放在基础样式中,比如 body、button 或 :root 的初始规则里:
body {
background-color: var(--bg-color);
color: var(--text-color);
transition: background-color 0.3s ease, color 0.3s ease;
}
-
transition必须作用于具体属性(如background-color),不是变量名本身 - 不要写
transition: --bg-color 0.3s—— 浏览器直接忽略,连警告都不报 - 所有用到变量的元素,只要涉及颜色/透明度/尺寸变化,都要显式加
transition
CSS 变量要配合具体属性使用,不能指望变量自己动
transition 对 --theme-color-primary 这类自定义属性完全无效。它只能作用于可插值的原生属性,比如 color、background-color、opacity、transform。
所以得靠「变量提供值 + 属性承载动画」这个组合:
立即学习“前端免费学习笔记(深入)”;
button {
background-color: var(--primary-color);
transition: background-color 0.25s ease-in-out;
}
- 变量只负责存值,动画由属性触发;改
--primary-color时,background-color才会平滑过渡 - 避免在
::before或::after伪元素里用变量 +transition,部分浏览器渲染延迟明显 - 如果用了
filter: brightness(var(--brightness)),filter支持过渡,但--brightness本身不能被transition监听
深色模式切换时容易漏掉的三个地方
即使写了 transition,仍可能闪烁或抖动,常见于以下三处没覆盖全:
-
body和html高度没设为min-height: 100vh,导致背景色切换时露出白边 - 字体大小、行高、阴影等未用变量统一管理,主题切换时尺寸突变引发布局抖动
- JS 切换 class 之前,页面已按默认主题渲染了一帧 —— 解决办法是在
<html>标签上预设初始 class(如class="light-theme"),避免 FOUC
别依赖 @media (prefers-color-scheme: dark) 自动切换,它不触发动画;必须用 class 控制,并确保该 class 在 DOM 加载前就存在。
缓动函数和时长选错,也会显得“刺眼”
哪怕 transition 写对了,参数不合理照样难看。0.3s 的 ease 是安全起点,但更推荐:
-
color 0.25s ease-in-out:比ease更柔和,进出都减速 - 避免
linear,匀速过渡在颜色变化中显得机械、不自然 - 别用
transition: all 0.3s,容易意外触发 margin/padding 等不可见属性的动画,引发抖动 - 超过 0.4s 会让人感觉延迟,低于 0.15s 则像没动一样
最易被忽略的是:父元素设置了 color,子元素又用了 inherit,会导致 transition 失效或行为异常 —— 建议所有关键文本元素都显式声明 color 并加 transition。


















