欢迎访问 老鱼笔记今天是
无障碍与显示设置

站点做到一定程度,一定会遇到这两个需求:换配色、加暗色模式。如果颜色散落在几十个组件里,这两件事都会变成体力活,而且极容易改漏。

两层变量结构

关键是把变量分成两层,各司其职:

:root {
  /* 第一层:色板。只定义"有什么颜色",不定义"用在哪里" */
  --p-navy-700: #14487e;
  --p-red-600: #c22b23;
  --p-gray-200: #dfe4ea;

  /* 第二层:语义。组件只认这一层 */
  --bg-surface: #ffffff;
  --fg-heading: #1c2024;
  --border: var(--p-gray-200);
  --link: var(--p-navy-600);
}

好处是:加暗色模式时,只需要重新赋值语义层,页面结构完全不用动:

html[data-theme='dark'] {
  --bg-surface: #171d25;
  --fg-heading: #eef2f6;
  --border: #2b333e;
  --link: #7cb6ef;
}

三种无障碍模式的实现

政务类站点通常需要字号调节、高对比度、纯文本模式。用同一套思路,把它们都做成“给 <html> 加属性”,样式层面自动响应:

模式 属性 实现方式
字号调节 data-fs="s|m|l" 改写 --fs-scale,所有字号基于它计算
高对比度 data-contrast="high" 覆写为黑底白字 + 黄色链接
纯文本 data-plain="on" 隐藏装饰元素、取消阴影与圆角

字号的做法值得展开一句:把字号定义成 calc(14px * var(--fs-scale)),那么调节字号只需要改一个系数,全站文字同步缩放。

:root {
  --fs-scale: 1;
  --fs-base: calc(15px * var(--fs-scale));
}

html[data-fs='l'] {
  --fs-scale: 1.15;
}

两个容易踩的坑

1. 首屏闪烁

主题存在 localStorage 里、由 JS 读取,就会出现“先渲染浅色、再跳成深色”的闪白。解决办法是在 <head> 里放一段内联脚本,在页面渲染前就把属性写上去:

<script is:inline>
  (function () {
    var el = document.documentElement;
    var saved = JSON.parse(localStorage.getItem('prefs') || '{}');
    var dark = saved.theme === 'dark' ||
      (saved.theme !== 'light' && matchMedia('(prefers-color-scheme: dark)').matches);
    el.dataset.theme = dark ? 'dark' : 'light';
  })();
</script>

内联脚本要尽量短,因为它是阻塞渲染的;同时注意它与主逻辑里的存储键必须保持一致。

2. 语义变量不够用

一开始容易只定义 --bg、--fg 两三个变量,做到一半发现导航条、页脚、引用块在暗色下都不对劲,只好回去补。经验是:先把页面上所有“角色”列一遍(页面底、卡片、次级底、描边、正文、次要文字、链接、导航底、导航文字、页脚底……),再开始定义。

小结

设计令牌的本质不是“变量多”,而是把决策点集中起来。集中之后,改配色是改文件,而不是改几十个组件。

信息来源:OldFish ·本站原创 · 发布时间:

本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。