译者:噼里啪啦
7 January, 2014
Sass中的虚类继承
这篇文章是关于我在写Sass时,使用的一个小技巧,并且是在做workshop时经常被问到的问题,同时很希望这个特性可以被加入到inuitcss的新版本中。
在写Sass的时候,有时需要对类进行抽象,我一般采用下面的方式实现:
.foo,
%foo {
color: red;
}
复制代码
这里有两个类名的原因也很简单:虚类仅在用@extend
继承时使用。
关于这一点Oliver J Ash 写过一篇很棒的文章详细讲述了其中的原理,非常推荐大家阅读。
简而言之,使用@extend
会带来如下问题:它会继承匹配到的每一个选择器,举例来说,你写了如下代码:
.foo {
color: red;
}
.footer .foo {
font-weight: bold;
}
.bar {
@extend .foo;
}
复制代码
你期望编译后的结果可能是下面这个样子的:
.foo, .bar {
color: red;
}
.footer .foo {
font-weight: bold;
}
复制代码
但是,每个使用过@extend
的程序员都是知道,你实际得到的结果可能是下面这个样子的:
.foo, .bar {
color: red;
}
.footer .foo, .footer .bar {
font-weight: bold;
}
复制代码
Sass使.boo
继承了每一个它能找到的.foo
实例。这是一个很简单的例子,关于深层次复杂的机理,Oliver的文章给出了更详细的描述。
为了规避这种正确但是非预期的行为,我想出了一个非常简单的办法:在使用@extend
的时候,保证其继承的元素只出现过一次。
有许多方法都达到这个目的,最简单的转换命名规则或者在已有类名前加上前缀就可以得到我们想要的结果,如下所示:
.foo,
.x-foo {
}
复制代码
在使用这种方法时我们需要牢记:只继承带有x-
前缀的元素,并且不在其他任何位置使用带该前缀的类名,这意味着在我们不期望的位置不会存在由@extend
产生多余的CSS文件。
这种方法最大的问题就是带有x-
前缀的类名依旧会出现在css文件中,好像问题不大,但是提出这种方法要避免的问题就是减少css中类的个数,这样做似乎有点得不偿失。
在这个问题上,显而易见的答案就是使用虚类代替有前缀的类,将:
.foo,
.x-foo {
}
复制代码
替换为:
.foo,
%foo {
}
复制代码
现在有了只会出现一次的虚类%foo
,我们可以大胆的使用它来进行@extend
操作了。这意味着我们可以限制继承类出现的位置,并且在编译过的样式文件中不会出现用来替代实体类的其它类名。
现在我们的到的Sass文件是这样的:
.foo,
%foo {
color: red;
}
.footer .foo {
font-weight: bold;
}
.bar {
@extend %foo;
}
复制代码
并且编译后的文件跟预期完全一样:
.foo,
.bar {
color: red;
}
.footer .foo {
font-weight: bold;
}
复制代码
总结规则如下:
-
在Sass中对限定的虚类只写一次
-
只
@extend
虚类 -
在定义样式时使用实体类,并且实体类可以出现多次
我们所做的一切只是确保被@extend
的选择器出现尽量少的次数
当然,这个答案并不是完美的,它仅仅取决于你坚持上述规则的能力。这种为了使用@extend
(其实我并不会经常使用)同时又消除它本身“贪婪”特性的做法有一点点hack。
有许多其它更好的方法来解决这个问题,我非常愿意听取别人的想法,当然上述是我解决这个问题的常用方法。我在jsfiddle.net/csswizardry… 里创建了一个使用虚类继承的mixin方法,以供大家参考。