youngwind/blog

css样式融合与类继承

youngwind opened this issue · 1 comments

前言

前一阵子用了一下css-module,有一个问题没有解决,那就是同样一个元素添加多个类名的情况。比如我想要这样的效果。这种做法很常见,一般用于.title定义公共样式,title#{n}定义各自独有的样式。

<div class="title title1"></div>
<div class="title title2"></div>

如果希望通过css-module来完成的话,代码大概是这样。

import style from "./index.scss"
<div className={style.title, style.title1}></div>
<div className={style.title, style.title2}></div>

但是会报错,因为官方的css-module只能接受一个变量字符串。
#1. 通过类名解决

当时找到了两个解决方案。

  1. 字符串拼接。
<div className={style.title + " " + style.title1}></div>

但是这种方法好搓啊。。。肯定有更优雅的解决方案。
2. react-css-module
这个loader可以直接定义多个类名,具体参考这里
#2. 通过样式继承解决

后来跟别人交流这个问题的时候得出以下的帮助:

官方说法,css-module在设计的时候就没打算支持多个类名,因为在他们看来,每一个元素应该像一个对象一样,只添加一个className值,至于样式的融合应该通过样式的继承来完成。

嗯,细细想来,还是很有道理的。这样每个元素最多只有一个类名,简洁多了。

scss的继承与占位符

在我用scss的继承去实现它的时候发现一个有趣的问题。

.title {
  height: 100px;
}

.title1 {
  @extend .title;
  background-color: blue;
}

.title2 {
  @extend .title;
  background-color: pink;
}

scss-lint会报语法警告,如下。
2016-01-20 9 29 34
查阅了一下,才发现scss的继承和占位符的细微区别。
上面的scss代码会被编译成这样子。

.title, .title1, .title2 {
  height: 100px;
}

.title1 {
  background-color: blue;
}

.title2 {
  background-color: pink;
}

但是如果我们不需要用到.title这个类呢?如果这个类唯一存在的作用就是抽象出公共的title1和title2那一部分呢?那么,用占位符要更好。

// scss 写法
%title {
  height: 100px;
}

.title1 {
  @extend %title;
  background-color: blue;
}

.title2 {
  @extend %title;
  background-color: pink;
}

编译之后是这样子的。

.title1, .title2 {
  height: 100px;
}

.title1 {
  background-color: blue;
}

.title2 {
  background-color: pink;
}

区别在于不再有.title这个类了。

css-module 有 composes 应该可以解决