Skip to main content

主题切换

主题切换

前端主题切换,其实就是切换 CSS,其中变化最大的就是颜色相关的属性、图片、Icon等。

解决方案

常用的解决方式是 CSS 变量及 CSS 样式或 CSS 预处理器及 CSS 样式。

CSS 变量

.primary{
--vt-c-bg: #fff;
}

.dark{
--vt-c-bg: #000
}

.layer{
background-color: var(--vt-c-bg);
}

CSS变量,当点击某个按钮的时候做切换,如果变换比较大内容较多,可能会出现白屏的情况。

CSS 预处理器

使用 CSS 预处理器强大的预编译功能,简单来说,就是把 CSS 先写好。

html.primary .layer{
color: #fff;
}

html.dark .layer{
color: #000;
}

使用 CSS 预编译器,一开始会把所有的主题样式涉及到的内容全部写好,当切换的时候,直接切换即可。使用这种方式,一开始可能出现白屏时间。

$themeMap:(
primary:(
app-container: #f3f6fd,
main-color: #1f1c2e,
secondary-color: #4A4A4A,
link-color: #1f1c2e,
link-color-hover: #c3cff4,
link-color-active: #fff,
link-color-active-bg: #1f1c2e,
projects-section: #fff,
message-box-hover: #fafcff,
message-box-border: #e9ebf0,
more-list-bg: #fff,
more-list-bg-hover: #f6fbff,
more-list-shadow: rgba(209, 209, 209, 0.4),
button-bg: #1f1c24,
search-area-bg: #fff,
star: #1ff1c2,
message-btn: #fff,
),
dark:(
app-container: #1f1d2b,
main-color: #fff,
secondary-color: rgba(255,255,255,.8),
projects-section: #1f2937,
link-color: rgba(255,255,255,.8),
link-color-hover: rgba(195, 207, 244, 0.1),
link-color-active-bg: rgba(195, 207, 244, 0.2),
button-bg: #1f2937,
search-area-bg: #1f2937,
message-box-hover: #243244,
message-box-border: rgba(255,255,255,.1),
star: #ffd92c,
light-font: rgba(255,255,255,.8),
more-list-bg: #2f3142,
more-list-bg-hover: rgba(195, 207, 244, 0.1),
more-list-shadow: rgba(195, 207, 244, 0.1),
message-btn: rgba(195, 207, 244, 0.1),
)
);

@mixin themeMixin {
@each $themeKey, $themeValue in $themeMap {
html.#{$themeKey} & {
$currentTheme: $themeValue !global;
@content;
$currentTheme: null !global;
}
}
}

@function getVar($key) {
@return map-get($currentTheme, $key);
}

@mixin background_color($color) {
@include themeMixin {
background-color: getVar($color) !important;
}
}

@mixin font_color($color) {
@include themeMixin {
color: getVar($color) !important;
}
}

@mixin border_color($color) {
@include themeMixin {
border-color: getVar($color) !important;
}
}

跟随系统

可使用媒体查询实现跟随系统主题切换:

@media (prefers-color-scheme: light) {
html{
color: #000;
background-color: #fff;
}
}

@media (prefers-color-scheme: dark) {
html{
color: #fff;
background-color: #000;
}
}

可通过 window.matchMedia API 来获取当前系统的主题:

const media = window.matchMedia('(prefers-color-scheme: light)')
// const media = window.matchMedia('(prefers-color-scheme: dark)')

const followSystemTheme = (e) => {
if (!e.target.matches) {
document.documentElement.className = 'dark';
} else {
document.documentElement.className = 'light';
}
}

media.addEventListener('change', followSystemTheme, false)