必须用 data-theme 控制皮肤而非 class,因其可避免样式失控、维护爆炸和布局错乱;所有样式须限定在 [data-theme] 下,且 data-theme 必须设在 根节点,确保切换安全可靠、语义清晰、正交解耦。

直接用 data-theme 控制皮肤,而不是靠 class 切换;所有皮肤样式必须限定在 [data-theme] 选择器下,否则换肤后 layout 崩、颜色错、协作维护爆炸。
为什么不能用 class 控制主题(比如 theme-dark)
挂 class 在 上看似简单,但实际会快速失控:
- 新组件一加,开发随手写
<div class="card">,样式却依赖 <code>body.theme-dark .card—— 某处 JS 动态移除了theme-dark,整块区域就回退成白底黑字 - 多人协作时没人敢删旧主题规则,半年 CSS 文件涨到 8000 行,
!important开始泛滥 - 主题色一改,所有
.header、.sidebar都得手动确认是否继承了当前 class,而语义标签天然带作用域边界 - 写法必须是
,不是 - CSS 规则全部基于
[data-theme="dark"]或[data-theme="blue"]编写,禁止出现.theme-dark这类 class 选择器 - 切换时只需
document.documentElement.setAttribute('data-theme', 'blue'),无 DOM 重绘风险,也不触发 layout thrashing - 每个皮肤对应一个独立 CSS 文件(如
skin-dark.css),但所有文件都只用[data-theme="xxx"]作为顶层作用域 - 语义标签(
<header></header>、<nav></nav>、<main></main>)不是摆设:CSS 可自然分层,例如[data-theme="dark"] header { background: #1e1e1e; } - 避免把皮肤逻辑塞进业务组件内部,比如
<button class="btn theme-red"></button>—— 主题应由容器统一注入,组件只负责语义 - 自定义属性按角色命名:
--color-primary、--surface-level-1,而不是--dark-bg这种绑定具体皮肤的命名 - 布局靠类名切换(如
layout-left/layout-top),它控制 HTML 结构排列方式,与data-theme无关 - 皮肤只管视觉变量(颜色、阴影、圆角等),不碰
display、flex-direction这类布局属性 - 如果某套皮肤里硬编码了
flex-direction: column,那它就不再是“皮肤”,而是“布局+皮肤混合体”,后续无法自由组合
data-theme 必须设在 根节点
这是唯一可信的皮肤锚点,JS 切换只动这一个属性,不碰 classList:
皮肤结构模板怎么组织才可维护
一套皮肤不是一堆 color 替换,而是完整 HTML + CSS 分层结构:
布局切换和皮肤切换必须解耦
后台里常混在一起的“布局”(侧边栏左/顶/隐藏)和“皮肤”(深色/蓝调/高对比)其实是两套正交机制:
真正难的是语义边界划分——不是写多少 CSS,而是决定哪些标签该承担什么责任。一个没语义的 <div class="container">,再好的皮肤系统也救不了它。</div>











