使用sass实现换肤

换季了,总觉得衣柜里还缺一件衣服,走,逛商场/某宝

人都想换衣服,何况网站。。。

换肤实现的方案也比较多,之前有 css变量实现换肤,现在的项目基本都使用了css预处理器(也可以使用css变量换肤),所以用sass来实现下

正常情况下 一般都是给根目录加一个属性 xxx 来实现的

css 复制代码
html[data-theme='light'] .item {
  background: #fff;
  color: #000;
}

html[data-theme='dark'] .item {
  background: #000;
  color: #fff;
}

本身代码就是老母猪戴胸罩---一套又一套(有几套主题就得写几套代码),自己全部手写的话,那真是厕所打灯笼--找shi,每个主题下的样式都写一次,人都要疯掉了,而且里面很多重复的颜色和代码,不好维护

利用css预处理器,来解决重复代码和书写麻烦的问题

css 复制代码
/* 颜色这些可以使用变量提出去 */
$themes: ( /* 结构 类似于js的对象 键名是不是字符都可以 */
  '': (
    bgColor: red,
    textColor: blue
  ),
  'light': (
    bgColor: #fff,
    textColor: #000
  ),
  'dark': (
    bgColor: #000,
    textColor: #fff
  )
);

可以使用 混合 来使用我们定义的变量 循环遍历map结构里面的变量来生产不同的东西,从而达到不手写重复的代码 而且方便后期拓展和增加主题

css 复制代码
@mixin useTheme() {
   /* $key 属性名字 light/dark */
  /* $value 属性值 */ 
  @each $key, $value in $themes {
    /* 每次循环把主题得值保存起来 需要注意的是  这个    $currentTheme是局部变量 需要加上 !global 提示为全局变量 */
    $currentTheme: $key !global;
    html[data-theme='#{$key}'] & { /* 这儿其实不加html也行 */
      @content;  /* useTheme 传过来得属性和值  */
    }
  }
}
.page {
  width: 100px;
  height: 100px;
  @include useTheme {
    background: red;
    color: blue;
  }
}

手动就生成了三套代码 一个字 爽 !

但现在调用混合的时候,css属性和值都是写死的,这很不科学,可以使用 函数 来实现 动态输入css属性的值

css 复制代码
@function getVal($key) {
  /* map-get 获取map里面属性的值 */
  @return map-get(map-get($themes, $currentTheme), $key);
}
.page {
  width: 100px;
  height: 100px;
  @include useTheme {
    background: getVal(bgColor); /* 函数实参 是不是字符串都可以 但是尽量统一 */
    color: getVal('textColor');
    border-color: getVal('textColor');
  }
}

实际效果就是

完整代码就是

css 复制代码
$themes: (
  '': (
    bgColor: red,
    textColor: blue
  ),
  'light': (
    bgColor: #fff,
    textColor: #000
  ),
  'dark': (
    bgColor: #000,
    textColor: #fff
  )
);
@mixin useTheme() {
  @each $key, $value in $themes {
    $currentTheme: $key !global;
    html[data-theme='#{$key}'] & { 
      @content;
    }
  }
}
@function getVal($key) {
  @return map-get(map-get($themes, $currentTheme), $key);
}
.page {
  width: 100px;
  height: 100px;
  @include useTheme {
   background: getVal(bgColor); 
    color: getVal('textColor');
    border-color: getVal('textColor');
  }
}

上面还是半自动,下面来个全自动的,属性名和值都从调用的时候传进来

css 复制代码
$themes: (
  '': (
    bgColor: red,
    textColor: blue,
    fs: 44px
  ),
  'light': (
    bgColor: #fff,
    textColor: #000,
    fs: 44px
  ),
  'dark': (
    bgColor: #000,
    textColor: #fff,
    fs: 44px
  )
);
@mixin useTheme() {
  @each $key, $value in $themes {
    $currentTheme: $key !global;
    html[data-theme='#{$key}'] & {
      @content;
    }
  }
}
@function getVal($key) {
  @return map-get(map-get($themes, $currentTheme), $key);
}

@mixin styles($style, $type) {
  @include useTheme {
    #{$style}: getVal($type);
  }
}

.page {
  width: 100px;
  height: 100px;
  @include styles('background', 'bgColor');
  @include styles('color', 'textColor');
  @include styles('font-size', 'fs');
}

/* 编译成的css */
.page {
  width: 100px;
  height: 100px;
}

html[data-theme=''] .page {
  background: red;
}

html[data-theme='light'] .page {
  background: #fff;
}

html[data-theme='dark'] .page {
  background: #000;
}

html[data-theme=''] .page {
  color: blue;
}

html[data-theme='light'] .page {
  color: #000;
}

html[data-theme='dark'] .page {
  color: #fff;
}

html[data-theme=''] .page {
  font-size: 44px;
}

html[data-theme='light'] .page {
  font-size: 44px;
}

html[data-theme='dark'] .page {
  font-size: 44px;
}

需要注意的是:

混合的使用方法,不同的写法有时候 让不熟悉的人困惑

css 复制代码
@mixin myStyle {
    font-size: 12px;
    color: #fdef92;
    font-weight: bold;
}
p{
    @include myStyle();
}

/* 编译成css代码 */
p{
  font-size: 12px;
  color: #fdef92;
  font-weight: bold;
}

/* 
定义混合的时候 myStyle 后面加不加 小括号() 都行
调用混合的时候也是一样  myStyle 后面加不加 小括号() 都可以

*/

还有就是混合传参:

css 复制代码
@mixin generStyle($style, $type) {
  /* 
   参数和@content 同时在同一个 混合里 存在 使用@include generStyle('color', #000)传参可以生效

    再这样调用就会报错
    @include useTheme {
      fonst-size: 12px;
    }
  */
  #{$style}: $type;
  @content;
}

@mixin generStyle1() { // 可以加小括号
  @content;
}
@mixin generStyle2 { // 可以不加小括号
  @content;
}
@mixin generStyle3 {
  background: yellow;
}
.a {
  @include generStyle('color', #000);
  //   @include useTheme {// 再这样调用就会报错
  //     fonst-size: 12px;
  //   }
}
.b {
  @include generStyle1 {
    font-size: 12px;
  }
}
.c {
  @include generStyle2 {
    font-weight: 600;
  }
}

.d {
  @include generStyle3;
}

所以在开发的时候应该注意保持统一的代码规范!

sass在线生成css 网址:www.wetools.com/sass-to-css

相关推荐
liangshanbo121520 分钟前
React Fiber:从“解决卡顿”到完整更新链路
前端·javascript·react.js
Timmy28 分钟前
前端转全栈笔记:讲框架之前,先把 TypeScript 这关过了
前端·人工智能·node.js
计算机魔术师33 分钟前
年收入650亿、亏420亿,Anthropic凭什么敢叫价万亿?
前端
Frag0ut33 分钟前
Chrome Canary 最新实验功能:AI Mode、按设备筛选历史记录与 Gemini 自动改密
前端·人工智能·chrome·dev·beta·canary·最新实验功能
anew___1 小时前
《从零手写操作系统 (19):Ext2文件系统实战——从内存到磁盘的跨越》
java·服务器·前端·数据库·算法
吴声子夜歌1 小时前
Nginx应用与运维——Nginx Web服务应用实战(HTTPS安全服务器的搭建)
运维·前端·nginx
liangshanbo12151 小时前
Monorepo 工程化面试题:如何设计 Web + Node.js 中间层 + Shared + Scripts 的 Monorepo?
前端·node.js
IT_陈寒1 小时前
Redis集群切换主节点时,服务竟然全员掉线
前端·人工智能·后端
wangbing11251 小时前
开发指南147-WebSocket-前端
前端·websocket·网络协议
吴声子夜歌1 小时前
Nginx应用与运维——Nginx Web服务应用实战(伪流媒体服务器的搭建)
运维·前端·nginx