Web组件适配用户/系统明暗模式 如何避免CSS代码重复?
解决Web组件明暗主题切换的CSS代码重复问题
以下是几种无需JavaScript、适配Stencil开发场景的方案,可避免重复编写主题判断规则:
1. 用全局自定义属性统一激活状态
在全局CSS中根据用户选择和系统主题,生成一个统一的开关变量--is-dark-active,组件内仅需判断该变量即可:
全局CSS配置
:root { --is-dark-active: 0; /* 浅色模式颜色变量 */ --tone-neutral-01: #000000; --tone-neutral-02: #333333; } /* 用户手动选择深色主题时激活 */ :root:has([style*="--global-pref-theme:dark"]) { --is-dark-active: 1; /* 深色模式颜色变量 */ --tone-neutral-01: #FFFFFF; --tone-neutral-02: #CCCCCC; } /* 用户选择跟随系统且系统为深色时激活 */ :root:has([style*="--global-pref-theme:system"]) { @media (prefers-color-scheme: dark) { --is-dark-active: 1; --tone-neutral-01: #FFFFFF; --tone-neutral-02: #CCCCCC; } }
组件内CSS简化写法
.tabs { background-color: var(--tone-neutral-01); border: 1px solid transparent; } /* 仅需判断统一的激活变量 */ @container style(--is-dark-active: 1) { .tabs { border-color: var(--tone-neutral-02); } }
注:若需兼容不支持
:has()的浏览器,可通过PostCSS的postcss-has-pseudo插件做降级处理。
2. PostCSS插件批量合并规则
借助postcss-custom-selectors和postcss-nested插件,自定义一个合并后的主题选择器,自动展开为所需的多条件规则:
安装依赖
npm install postcss-nested postcss-custom-selectors --save-dev
PostCSS配置
// postcss.config.js module.exports = { plugins: [ require('postcss-nested'), require('postcss-custom-selectors')({ preserve: false }) ] };
组件内CSS写法
/* 自定义合并选择器 */ @custom-selector :--dark-active @container style(--global-pref-theme: dark), @container style(--global-pref-theme: system) @media (prefers-color-scheme: dark); .tabs { background-color: var(--tone-neutral-01); border: 1px solid transparent; } /* 复用自定义选择器 */ :--dark-active { .tabs { border-color: var(--tone-neutral-02); } }
3. Tailwind CSS自定义变体
若使用Tailwind,可在配置中定义一个包含两种深色触发条件的自定义变体,组件内直接用类名复用:
Tailwind配置
// tailwind.config.js module.exports = { plugins: [ function({ addVariant }) { addVariant('dark-active', [ '@container style(--global-pref-theme: dark) &', '@container style(--global-pref-theme: system) @media (prefers-color-scheme: dark) &' ]); } ], theme: { extend: { colors: { 'neutral-01': 'var(--tone-neutral-01)', 'neutral-02': 'var(--tone-neutral-02)' } } } };
组件内HTML写法
<div class="tabs bg-neutral-01 border-transparent dark-active:border-neutral-02"> <!-- 组件内容 --> </div>
4. Stencil全局样式注入
利用Stencil的globalStyle特性,将主题判断逻辑注入全局样式,所有组件共享统一的激活变量,无需每个组件重复编写规则。
内容的提问来源于stack exchange,提问作者vitto
相关产品推荐
相关产品推荐

