likes
comments
collection
share

前端主题色修改方案解析与实践

作者站长头像
站长
· 阅读数 7

在前端开发中,修改主题色方案通常可以通过以下几种方式实现:

1. CSS变量(CSS Custom Properties):

使用CSS的变量功能,由 var()函数来获取值(比如: color: var(--main-color);),结合使用修改html或body上属性,在全局或局部范围内使用这些变量,通过修改变量的值来改变主题颜色。

案例:

Taro官网动态修改data-theme属性值 前端主题色修改方案解析与实践

MDN官网 动态修改html上class dark/light 前端主题色修改方案解析与实践

应用:

CSS变量(CSS Custom Properties):

动态更改,定义亮色/深色调css变量,颜色或图片都可以使用这种方式更改:

/* 亮色调默认颜色 */
.root-light {
  --primary-color: red;
}
/* 深色调默认颜色 */
.root-dark {
  --primary-color: blue;
}

button {
  background-color: var(--primary-color);
}

在切换主题色方法中动态更新,在html中通过js修改深色调/亮色调class,应用到的颜色变量的元素会自动更新对应的颜色:

const theme = 'dark';
const body = document.querySelector("body");
body.classList.add(`root-${theme}`);

优缺点:

  • 优点:

    • 灵活性高,可以在整个应用程序中定义和使用变量,可以动态修改主题色,实现即时切换效果。
    • 适用于单个应用程序或网站的主题修改,不需要额外的工具或依赖。
  • 缺点:

    • 兼容性受限,低版本的浏览器可能不支持CSS变量,但现在项目一般只会要求主流浏览器了吧。

前端主题色修改方案解析与实践 - 需要手动在代码中添加对CSS变量的支持,可能增加一些开发成本。

2. 预处理器(Preprocessor):

使用CSS预处理器如Sass、Less或Stylus等,可以定义变量来表示主题颜色,然后在样式表中使用这些变量来设置具体的颜色。通过修改变量的值,可以轻松地修改整个应用程序的主题色。

案例:

element uianted design 都是采取预处理器方式动态修改主题色。

应用:

预处理器(Preprocessor)

/* 定义主题颜色变量 */ 
$primary-color: #ff0000; 
/* 使用主题颜色变量 */ 
button { 
    background-color: $primary-color; 
}

在上面的示例中,我们使用 Sass 预处理器来定义一个名为 $primary-color 的变量,并在button 元素的样式规则中使用该变量来设置背景颜色。如果要更改主题颜色,只需修改变量的值即可。

优缺点:

  • 优点:

    • 提供了更强大的功能,例如变量、混合器等,可以更便捷地定义和修改主题色。
    • 可以根据需求轻松切换不同的主题样式文件。
  • 缺点:

    • 需要额外学习和配置样式预处理器,增加了一些开发复杂性。
    • 需要编译预处理器的源代码,可能增加了一些构建步骤和性能开销。

3. 扩展-根据主题色切换图片

以上两种方案都是可以通过定义变量方式指定不同主题色下的图片。另外,我们也可以在主题色切换时保存色值,使用js计算在哪个色区范围内,动态更改内联图片路径。

以下方法判断一个颜色是否属于红色系列的函数。它接受一个十六进制颜色值作为参数。函数颜色值转换为 RGB 值,并使用 rgbToHsl 辅助函数将 RGB 值转换为 HSL 值。最后,判断 HSL 值的色调是否在红色系列范围内(0°-30°和330°-360°),如果是,则返回 true,否则返回 false。


function isRedColorSeries(hexColor) {
  // 去除可能的 # 前缀
  if (hexColor.startsWith('#')) {
    hexColor = hexColor.substring(1);
  }

  // 转换为 RGB 值
  let red = parseInt(hexColor.substring(0, 2), 16);
  let green = parseInt(hexColor.substring(2, 4), 16);
  let blue = parseInt(hexColor.substring(4), 16);

  // 转换为 HSL 值
  const hsl = rgbToHsl(red, green, blue);

  // 判断色调是否在红色系列范围内
  return (hsl.hue >= 0 && hsl.hue <= 30) || (hsl.hue >= 330 && hsl.hue <= 360);
}

// RGB 值转换为 HSL 值的辅助函数
function rgbToHsl(red, green, blue) {
  red /= 255;
  green /= 255;
  blue /= 255;

  const max = Math.max(red, green, blue);
  const min = Math.min(red, green, blue);
  let h, s, l = (max + min) / 2;

  if (max === min) {
    h = s = 0; // achromatic
  } else {
    const d = max - min;
    s = l > 0.5 ? d / (2 - max - min) : d / (max + min);

    switch (max) {
      case red:
        h = (green - blue) / d + (green < blue ? 6 : 0);
        break;
      case green:
        h = (blue - red) / d + 2;
        break;
      case blue:
        h = (red - green) / d + 4;
        break;
    }

    h /= 6;
  }

  return {
    hue: Math.round(h * 360),
    saturation: Math.round(s * 100),
    lightness: Math.round(l * 100)
  };
}

export default isRedColorSeries;

例:如果是红色系主题色,引入红色系图片,否则为蓝色系图片。

<template>
  <div>
    <img
      :src="require(`@/assets/steps/${isRed ? 'red' : 'blue'}-03.png`)"
    />
  </div>
</template>

<script>
import isRedColorSeries from "@/utils/isRedColorSeries";

export default {
  data() {
    return {
      isRed: isRedColorSeries(),
    };
  },
};
</script>