主题控制必须使用html[data-theme="dark"],而非body类或:root.dark;所有主题修饰符需带--theme-前缀,css变量须设fallback,组件内禁用主题类名,仅通过css自定义属性响应主题。

主题类名必须挂载在 html 元素上,用 data-theme 属性控制
直接在 body 或容器上加 app--theme-dark 类是错的——它既不是你定义的 Block,也不支持系统偏好自动同步。真正可控的方式是操作 document.documentElement.dataset.theme = 'dark',让 CSS 通过 html[data-theme="dark"] 选择器响应。
常见错误现象:页面切暗色后部分组件没变、select 下拉框文字看不清、SSR 首屏白屏。根本原因是用了 body--dark 或 :root.dark 这类非法写法,导致变量未注入、原生控件样式被强制覆盖、构建时样式被 PurgeCSS 误删。
-
html[data-theme="dark"]是唯一推荐的根级控制方式,浏览器能正确响应window.matchMedia('(prefers-color-scheme: dark)') - 服务端渲染时,需提前根据 Cookie / User-Agent 写入
,否则 JS 加载前变量无值 - 所有 CSS 变量必须带 fallback:
color: var(--text-primary, #333);,否则 SSR 或 JS 失败时直接白屏
app 这类顶层 Block 的修饰符命名必须带 --theme- 前缀
如果你确实需要一个顶层 Block(比如包裹整个应用的容器),它的主题修饰符必须显式声明为 app--theme-dark,而不是 app--dark 或 dark-app。前者语义清晰、可被 PostCSS 插件静态分析;后两者要么被识别为新 Block,要么破坏 BEM 主语结构。
多个主题共存时(如深色+高对比度),应叠加修饰符:app app--theme-dark app--theme-high-contrast,而不是拼成 app--theme-dark-high-contrast——修饰符不可嵌套,也不可连写。
如果你了解HTML,CSS和JavaScript,您已经拥有所需的工具开发Android应用程序。本动手本书展示了如何使用这些开源web标准设计和建造,可适应任何Android设备的应用程序 - 无需使用Java。您将学习如何创建一个在您选择的平台的Android友好的网络应用程序,然后转换与自由PhoneGap框架到一个原生的Android应用程序。了解为什么设备无关的移动应用是未来的潮流,并开始构建应用程序,提供更
-
app--theme-dark合法,app--dark非法:BEM 要求主题修饰符必须含--theme-前缀,以区分状态类(如button--disabled) - 禁止在组件内部硬写主题逻辑,比如
.button--primary.button--dark—— 这把环境状态和组件角色耦合,破坏正交性 - 若用 Sass,可用
@at-root .app--theme-dark { .button { ... } }提升作用域,比嵌套更可控且不生成后代选择器
组件内响应主题靠变量,不是靠新增修饰符
别写 button--dark、card--high-contrast 这类类名。BEM 修饰符只表达组件自身角色或状态(button--primary、button--loading),不承担“当前主题是什么”的职责。主题响应应全部交给 CSS 自定义属性驱动。
容易踩的坑是:在 button--primary 里直接写 background: #333,结果换主题时无法热替换;或者把变量定义在 :root.dark 里,但 :root 不支持属性选择器,data-theme 变化时变量不会更新。
- 正确做法:
html[data-theme="dark"] .button--primary { --btn-bg: #333; --btn-text: #fff; } -
.button--primary自身只声明结构和角色,颜色、边框、阴影等全部由var(--btn-bg)注入 - 所有主题相关样式必须收在按组件组织的文件里(如
button.css),而不是拆成light.css/dark.css—— 否则加载顺序不确定,变量覆盖失效
PostCSS 和 lint 工具要放行 html[data-theme] 类型选择器
默认的 BEM lint 规则(如 stylelint-selector-bem-pattern)会把 html[data-theme="dark"] .button--primary 当作违规,因为它不符合 block__element--modifier 格式。这不是 bug,是你需要主动配置忽略。
否则 CI 构建失败、编辑器报红、团队成员反复修改,反而阻碍落地。
- 在
.stylelintrc中添加:"ignoreSelectors": ["html\[data-theme.*?\]"] - PostCSS 插件(如
postcss-bem-linter)同理,需显式 exclude 含data-theme的规则 - 若用 TypeScript + CSS Modules,确保
import styles from './Button.module.css'返回的类名仍符合 BEM 约定,不被 Webpack 默认哈希打乱语义
--dark 塞进组件类名,就等于把全局决策权下放到每个按钮、每张卡片里——后续维护成本会指数级上升。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










