动态link标签加载不同主题css
**原理:**提前准备好几套CSS主题样式文件,在点击切换主题时,创建link标签动态加载到head标签中,或者是动态改变link标签的href属性。
缺点:
动态加载样式文件,如果文件过大网络情况不佳的情况下可能会有加载延迟,导致样式切换不流畅
维护不便!
**优点:**实现了按需加载,提高了首屏加载时的性能且兼容性好
- 先创建主题css文件
dark.css
、light.css
等 - html中link引入
html
<head>
<link rel="stylesheet" href="./css/dark.css" >
<link rel="stylesheet" href="./css/light.css" disable>
</head>
- 切换主题
typescript
const themesCssSheet = [
document.querySelector("link[data-theme='light']"),
document.querySelector("link[data-theme='dark']"),
]
btn.addEventlistner("click",()=>{
const dataTheme = btn.getAttribute("data-theme")
themesCssSheet.forEach(theme=>{
t.disable = theme.dataset.theme === dataTheme
})
})
提前引入不同主题的css样式,通过切换类名切换主题
- 定义好css样式
css
/* light样式主题 */
body{
color: #f90;
background: #fff;
--text-color:black
--header-bg:orange
}
/* dark样式主题 */
.dark {
color: #eee;
background: #333;
--text-color:#fff
--header-bg:blue
}
- 点击切换主题时 js切换
typescript
document.body.classList.toggle("dark")
css预编译器
scss
$themes:(
light:(
textColor:black
headerBg:orange
),
dark:(
textColor:#fff
headerBg:blue
)
)
$currentTheme:light;
@mixin changeTheme(){
@each $key,$value in $themes{
$currentTheme:$key !global;
html[data-theme='#{$key}'] & {
@content;
}
}
}
@function getTextColor(){
$currentThemeObj: map-get($themes,$curTheme);
@return map-get($currentThemeObj,"textColor");
}
@function getHeaderBg(){
$currentThemeObj: map-get($themes,$curTheme);
@return map-get($currentThemeObj,"headerBg");
}
@function getThemeValue($key){
$currentThemeObj: map-get($themes,$curTheme);
@return map-get($currentThemeObj,$key);
}
.content{
width:100%;
height:100%;
@changeTheme{
textColor:getTextColor();
headerBg:getHeaderBg();
}
}
基于CSS变量(最优方式)
原理 :根据html元素标签的属性切换所使用的主题变量。
缺点 :IE兼容性不行(基本可以忽略)。
优点:便于维护,基本无需css参与
- 定义两套(多主体多套)变量
css
:root{
--text-color:black
--header-bg:orange
...
}
// 暗色主题
html[data-theme='dark']{
--text-color:#fff
--header-bg:blue
...
}
- 在main.js项目入口文件导入该变量,便于组件使用
- 组件中主题相关的直接使用变量
- 主题切换时
typescript
type Theme = "dark" | "light"
export const changeTheme = (theme:Theme )=>{
document.documentElement.dataset.theme = theme
}
CSS变量+动态setProperty
- 定义变量
css
:root{
--text-color:black
--header-bg:orange
...
}
- 定义js更改属性值方法
typescript
export const setCssVar = (prop: string, val: any, dom = document.documentElement) => {
dom.style.setProperty(prop, val)
}
// 当样式改变
setCssVar('--text-color', color)
总结
还有其他方式(例如vue3 v-bind css,变量和类名结合),但是总体都大同小异。