实现css换肤的方案有很多,可以使用less和sass,原子化css(Tailwind CSS、Windi CSS、UnoCSS...)
其实也可以使用css变量来实现
什么是css变量
自定义属性(有时候也被称作CSS 变量或者级联变量)是由 CSS 作者定义的,它包含的值可以在整个文档中重复使用。由自定义属性标记设定值(比如: --main-color: black;),由 var() 函数来获取值(比如: color: var(--main-color);
为什么要用它
同样一个颜色值可能在很多地方被使用到,如果这个值发生了变化,需要全局搜索并且一个一个替换(想想都头大)。这个时候css变量的好处就体现出来了,自定义属性在某个地方存储一个值,然后在其他许多地方引用它。另一个好处是语义化的标识。比如,--default-text-color 会比 #00f112 更易理解,尤其是这个颜色值在其他上下文中也被使用到。自定义属性受级联的约束,并从其父级继承其值。
如何使用
css变量是以两个减号(--)开头(因为$被sass用掉了,@被less用掉了 哈哈哈哈),后面的化就基本属于随便写了(CSS选择器不能是数字开头,JS中的变量是不能直接数值的,但是,在CSS变量中,这些限制通通没有,可以是数字,很多博文说可以是汉字,现在应该是不行了,会报错了)
css
:root {
--1:#fff ;
}
body {
background-color: var(--1);
}
属性值则可以是任何有效的 CSS 值。和其他属性一样,自定义属性也是写在规则集之内的
一般都是写在根 :root 下面,这样就可以在 HTML 文档的任何地方访问到它了
当然 你也可以把变量放在其他你需要的地方
使用的时候 就用 var(csss变量来使用)
css
/* 全局声明 */
:root {
--default-bg-color: #fff;
}
.className{
background-color:var(--default-bg-color)
}
/* 局部声明 */
body {
--foo: #ed145b;
--bar: #F7EFD2;
}
详解 var()
var函数的第一个参数是自定义属性的名称,如果提供了第二个参数,则表示备用值,当自定义属性值无效时生效。
第二个参数可以嵌套,但是不能继续平铺展开下去了,例如:
css
.className{
background-color:var(--default-bg-color,red) /* --default-bg-color无效的时候 就是红色了 */
}
.demo{
background-color:var(--default-bg-color,var(--main-bg-color,red)) /* --default-bg-color 和 --main-bg-color 都无效的时候 就是红色了 */
}
在js里面操作css变量
在 JavaScript 中获取或者修改 CSS 变量和操作普通 CSS 属性是一样的:
js
// 获取一个 Dom 节点上的 CSS 变量
dom.style.getPropertyValue("--my-var");
// 获取任意 Dom 节点上的 CSS 变量
getComputedStyle(dom).getPropertyValue("--my-var");
// 设置 Dom 节点上的 CSS 变量
dom.style.setProperty("--my-var", '#7F583F');
// 删除变量
document.body.style.removeProperty('--primary'); //局部
需要注意的
-
变量值只能用作属性值,不能用作属性名
css.foo { --mt: margin-top; /* 很显然,下面是无效的 */ var(--mt): 20px; }
-
如果变量值是一个字符串,可以与其他字符串拼接
css--str1: 'hello'; --str2: var(--bar)' world'; // 示例 body:before { content: '--screen-category : 'var(--screen-category); }
-
如果变量值是数值,不能与数值单位直接连用 可以和 calc 配置使用
cssfoo { --gap: 20; /* 无效 */ padding-top: var(--gap)px; /* 通过calc去计算,有效 */ padding-top: calc(var(--gap) * 1px); }
-
如果变量值带有单位,就不能写成字符串
css.foo { --gap: '20px'; gap: var(--foo); /* 不生效 不能写成字符串 */ } .foo { --gap: 20px; gap: var(--foo); /* 有效 */ }
实操
来实现一个小demo(因为是小demo,重点在实现功能,所以很多方便开发的工程化配置就没搞)
有三个按钮 点击不同的按钮 需要实现不同主题色的切换
js
const [currentColor, setCurrentColor] = useState(
sessionStorage.getItem("homeColor") || "themeGreen"
);
const setBgColor = (str: string) => {
setCurrentColor(str);
sessionStorage.setItem("homeColor", str);
};
const items = [
{
key: "1",
label: (
<span
className={cx("green", currentColor === "themeGreen" && "active")}
onClick={() => {
setBgColor("themeGreen");
}}
>
绿色
</span>
),
},
{
key: "2",
label: (
<span
className={cx("yellow", currentColor === "themeYellow" && "active")}
onClick={() => {
setBgColor("themeYellow");
}}
>
黄色
</span>
),
},
{
key: "3",
label: (
<span
className={cx("blue", currentColor === "themeBlue" && "active")}
onClick={() => {
setBgColor("themeBlue");
}}
>
蓝色
</span>
),
},
];
配置css变量
注意:三个主题类名下面都有一个共同的变量 --text-27282c
点击不同的颜色按钮 看看 变化
原理就是 利用本地储存来获取当前的主题类名,然后在需要做换肤的地方使用css变量,但是css变量是同一个,主题类名下这个css变量却可以是不同的值,利用这个就实现了简单换肤