令牌单一出处
主题 token 各页各写一份,第 N+1 个页面必然漏:真实事故是首页和详情页都换了皮肤,专题页还是硬编码的旧色。
右上角切一次:整页颜色交叉淡化(视图过渡),选择写进 localStorage,刷新保持。
从没点过的用户不看这段脚本 —— 没有 data-theme 属性时,页面直接跟随系统的
prefers-color-scheme,并且把按钮藏起来:宁可不显示,也不给一个点不动的假开关。
点下面任一张卡:2 秒缓入缓出滚到卡片区。中途滚轮 / 触摸 / 方向键一动作就交还控制权,
prefers-reduced-motion 下直接瞬移。原生 scrollIntoView({behavior:'smooth'})
的时长由浏览器定(约 300ms),要"能看清的过程"只能 rAF 自算。
主题 token 各页各写一份,第 N+1 个页面必然漏:真实事故是首页和详情页都换了皮肤,专题页还是硬编码的旧色。
属性贴 <html> 上,而各页自己的 :root 通常写在后面、特异性同为 (0,1,0) —— 选择器不带元素名前缀就会被压掉:属性切了、颜色纹丝不动。
存过的主题必须在 <head> 里先贴一次,否则刷新先闪一帧默认主题。
重映射要覆盖页面用到的全部 token,漏一个就是"切了一半"。
没有属性时用 @media (prefers-color-scheme) 跟随系统,并隐藏按钮 —— 点不动的开关比没有开关更糟。
原色 --accent 只给图形和大字号;彩色小字必须用同色相提亮/压暗一档的 --accent-ink。
44px 热区、15px 图标、无边框无胶囊无文字;禁两个圆点并排。
隐藏画布 ≠ 停渲染:给常驻动效挂主题判断,浅色下别继续烧 GPU。
DOM / CSS 提示与动画 / JS 绑定 / 过期闸 / 别处仍在用的附带物,一层不落。
备选主题冷启动时背景帧数应为一帧都没跑 —— 拿计数说话,不靠"看起来停了"。
html[data-theme] 翻转,上面 computed --bg 跟着变。localStorage.theme 还在,首屏直接是选过的颜色(全程无闪)。