Less,更加高效好用的CSS(iii)

前言

前面的一个章节中我们详细的介绍了less中的最为重要的混合的知识,现在我们要进行说明的是less中的继承。继承这个玩意似乎并不是很重要,为什么呢?因为我在less的官网中没有找到任何有关的教程,就算是上网上去搜索相关的文章也没啥好看的,大多是三言两语,这就是继承什么什么的。在这里我们就来好好的看看less中的继承到底是个啥吧。

混合的一点缺陷

在前面的几篇文章中把组合中我们常说的类之间的关系组合或者说混合进行比较,发现他们似乎真的是蛮相似的。现在又来了一个继承,这就不是相似的问题了,这是完全一样。不过这个既然是继承,解决的肯定是那种父类子类的那种拓展的问题。比如说,现在有一个基本的样式,但是在这个基本样式的前提下还有其他几个更加特殊的样式(也就是说在基本样式的基础上,增加了几个行的样式)。这样的问题该如何解呢?

我想,人们的第一反应肯定是使用混合。将基本的样式写成一个混合,然后再特殊的样式中调用这个混合。比如如下的代码。

.basestyle {
    background-color: red;
    color: #008000;
    margin-left: 20px;
    border: 1px solid blue;
}

.special-style1 {
    .basestyle();
    padding: 20px;
    vertical-align: middle;
}

.special-style2 {
    .basestyle();
    vertical-align: baseline;
    margin-top: 10px;
}

.special-style3 {
    .basestyle();
    box-shadow: 0 0 3px black;
    border-radius: 10px;
}

问题似乎很简单的就解决了(此时使用组合基类中没有使用括号,因为基类中的样式可能也要被使用,在没有使用参数的情况下是没有必要加上括号的)。不过先让我们来看一下这个编译的结果如何。

.basestyle {
  background-color: red;
  color: #008000;
  margin-left: 20px;
  border: 1px solid blue;
}
.special-style1 {
  background-color: red;
  color: #008000;
  margin-left: 20px;
  border: 1px solid blue;
  padding: 20px;
  vertical-align: middle;
}
.special-style2 {
  background-color: red;
  color: #008000;
  margin-left: 20px;
  border: 1px solid blue;
  vertical-align: baseline;
  margin-top: 10px;
}
.special-style3 {
  background-color: red;
  color: #008000;
  margin-left: 20px;
  border: 1px solid blue;
  box-shadow: 0 0 3px black;
  border-radius: 10px;
}

说实话,不用我说是个人都应该能知道其中的问题所在——样式是真的赘余了。我们理应当使用,选择器将基类和子类的样式统统写在一起的。你要是说这种写法是否解决了这个问题,还真的是解决了这个问题,只能说解决的方式不够优雅,less给我们提供了一种全新的方式来解决这个问题——那就是继承。

继承的使用

less中的继承也是使用extend关键词(可见Java的影响力是多么的大),不过使用的方式不像是组合的那个函数那样,而是有一点儿像CSS中的伪类(before, after, hover, focus),下面使用继承的方式解决上面的问题。

.basestyle {
    background-color: red;
    color: #008000;
    margin-left: 20px;
    border: 1px solid blue;
}

.special-style1:extend(.basestyle) {
    padding: 20px;
    vertical-align: middle;
}

.special-style2:extend(.basestyle) {
    vertical-align: baseline;
    margin-top: 10px;
}

.special-style3:extend(.basestyle) {
    box-shadow: 0 0 3px black;
    border-radius: 10px;
}

在对应的子类的后面写上:extend(需要继承的类),之后子类就拥有了父类的所有的样式,而且是没有赘余的那种。上面的代码编译结果如下。

.basestyle,
.special-style1,
.special-style2,
.special-style3 {
  background-color: red;
  color: #008000;
  margin-left: 20px;
  border: 1px solid blue;
}
.special-style1 {
  padding: 20px;
  vertical-align: middle;
}
.special-style2 {
  vertical-align: baseline;
  margin-top: 10px;
}
.special-style3 {
  box-shadow: 0 0 3px black;
  border-radius: 10px;
}

这样的编译出来的代码才是真正的赏心悦目,足够的优雅。

其实继承也是足够的容易理解的,上面基本上就是继承的全部用法了,下面就简单的对继承进行一些说明。

继承的其他说明

不能使用参数

我们不能在继承中像组合那样子使用参数,也就是说继承是不够灵活的。其实仔细想想也是很容易想明白的,什么时候我们需要写有参数的继承呢?那么这个使用使用混合不是刚刚好吗?反正又不会重复。所以说继承中实在是没有必要拥有参数。

既然是肯定不能有参数,那么就意味着继承的基类是肯定要要less编译到CSS文件中去的,不过这似乎并不是一个问题。

不能使用变量选择器

变量选择器是什么东西?Talk is cheap, show me the code!

@selector = .parent-class;
@{selector} {
    color: red;
}

.base-class:extend(.parent-class) {} // Error!
.base-class:extend(@{selector}) {} // Error!

上面的两种写法都是错误的写法,不过这次说实话我也不知道为啥这个不可以用。既然人家已经告诉你这种情况下不可以使用继承,那么就避免在这种情况下使用继承吧。(不过说实话实现变量选择器就已经很少了,还要对它进行继承,这种情况属实时有点儿罕见的。)

可以使用嵌套选择器

这种写法也是很少的我感觉,简单的了解一下就行了。

div {
    span{
        color: red;
    }
    color: black;
}

.speclass {
    &:extend(div span);
}

上面我们顺便的补充了两个相关的知识点,继承不只是使用.类,其他的比如id tag都是可以的,只不过使用类是最好的罢了。还有就是继承的时候,也可以在类中使用&:extend(继承),因为&代表的就是父类的选择器.speclass

然后就是回到主题,嵌套的选择器div span也是可以继承的。

编译结果如下。

div {
  color: black;
}
div span,
.speclass {
  color: red;
}

精确匹配

当我们使用继承的时候,继承的选择器必须要和我们定义的选择器完整的匹配。比如

div .a {
    color: red
}

.b:extend(.a) {} // Error!

虽然上面div .a.a选择的都是同一个,但是如果只写一个.a,less是无法匹配样式的,我们必须将样式写全了才能够继承。

div .a {
    color: red
}

.b:extend(div .a) {}

分组选择器的继承问题

.class1, .class2 {
    color: red;
}

.class1 {
    margning: 10px;
}

.class2 {
    padding: 20px
}

.base:extend(.class1, class2) {}

对于继承中的分组选择器会每个单独继承,所以上面的代码相当于如下。

.base {
    &:extend(.class1);
    &:extend(.class2);
}

编译的结果如下。

.class1,
.class2,
.base {
  color: red;
}
.class1,
.base {
  margning: 10px;
}
.class2 {
  padding: 20px;
}

继承中属性的覆盖问题

来想想这么的一个问题,如果我们当前类中和继承的类中有相同的属性会怎么样?当前的类会覆盖基类?还是和他们写的顺序有关?那就是实践一下看看到底会怎样。

.bbase {
    color: red;
}

.spe:extend(.bbase) {
    color: black;
}

编译结果如下。

.bbase,
.spe {
  color: red;
}
.spe {
  color: black;
}

.spe来说两个选择器的优先级是相同的,那么下面的子类中写的color就会覆盖上面的color

不过这个顺序是固定的嘛?基类就要在上面,子类就要在下面?当然不是。

.spe:extend(.bbase) {
    color: black;
}

.bbase {
    color: red;
}

现在我们将less中子类父类的位置换一下,看一下编译的结果。

.spe {
  color: black;
}
.bbase,
.spe {
  color: red;
}

( ⊙ o ⊙ )啊!子类中的属性竟然被父类给覆盖了,这岂不是滑天下之大稽??要避免这样的结果,我们需要尽量将要被继承的类写在源文件的上面,防止父类覆盖子类这类事件的发生。

总结

继承中的内容蛮少的,我们可以很简单的写完继承的基本上所有的内容,但是仅仅知道了继承是个啥,不知道继承怎么用也是没啥用的,后面准备针对bootstrap中的栅格布局的源码分析一下less的使用。


一枚小菜鸡