CSS语法不支持递归定义的表达式,因此你没有办法用一个语句定义一个启发式的规则。css
好比这样的需求:“.w
后面跟着一个数字,这个数字表明着width为百分之多少”(bootstrap的栅格系统就包含12种相对父级宽度的类定义)。
尽管彻底是一个规则里定义出的,但你只能这样写CSS:python
.w1 { width: 1% }
.w2 { width: 2% }
/** .w3 ... ... .w99 **/.w100 { width: 100% }
这样将形成很大的冗余,修改费时费力。但若是预编译CSS,就很是简单了:web
@maxnumber : 100 ;
.makeWidthRules(@number) when(@number <= @maxnumber ){
.w@{number}{ width: 1% * @number ;
}
.makeWidthRules(@number + 1) ;
}
.makeWidthRules(1) ;
使用纯CSS,咱们能够抽象出一些经常使用的布局CSS属性组合,经过CSS的类组合来达成常见的mixin式复用。
好比这样:chrome
<style>.tc { text-align: center; }.m { margin-left: auto; margin-right: auto; }.w50p { width: 50%; }.db { display: block; }</style><div class="tc m w50p"><img class="db"></div>
这种方案有几个问题:gulp
ul
下面的img.db
容许是display:block
”的规则,写成ul img.db { display: block; }
就彻底跑偏了——它违背了你建立这个.db
类时的本意,形成了代码的可读性和可维护性降低。若是你要改动规则,须要同时修改HTML和CSS,也可能形成新的样式问题。若是咱们想要创建一种代码风格,只容许CSS Class表明UI模块的抽象——改动样式时不至于通知后端改模板——咱们就要将上面这个例子的tc m w50p
换用一个有实际语义的类名如headwrap
,而后在CSS内部实现mixin。
——而这正是CSS的短板,CSS体系内的用法只有复制粘贴。bootstrap
至于如何用预编译语言作mixin,一个很是好的SASS示例由 segmentfault
在 里给出,容我摘录一小段:.btn-standout {
@extend .btn;
@extend .btn-block;
@media (max-width: $screen-xs-max) {
@include button-size(
$padding-large-vertical,
$padding-large-horizontal,
$font-size-large,
$line-height-large,
$border-radius-large
);
}
&.sell {
@extend .btn-primary;
}
}
进入CSS3的时代,旧式CSS hack如filter
,新式兼容前缀如-webkit-
等,都是冗余,修改的时候也须要修改多处,不容易维护。后端
好比对rgba背景的兼容:浏览器
.bg { filter: progid:DXImageTransform.Microsoft.gradient(startcolorstr=#ccff825b,endcolorstr=#ccff825b); }:root .bg { -ms-filter: none; background: rgba(255,130,91,0.8) }
在LESS里面,写个函数就能解决,屡次复用也不须要看到如此之多的hack:ruby
.rgbaBG(@c , @a){
@rgba : rgba(red(@c),green(@c),blue(@c),@a);
@shim : argb(@rgba) ;
filter: ~"progid:DXImageTransform.Microsoft.gradient(startcolorstr=@{shim},endcolorstr=@{shim})" ;
:root & {
-ms-filter: none ;
background: @rgba ;
}
}
.bg {
.rgbaBG(#ff825b, 0.8) ;
}
此外,使用LESS时,能够很方便地使用base64 data uri的方案。不须要直接面临在CSS中一大坨字符:
.bg { background: data-uri('../data/image.jpg'); }
SASS的相似方案见评论。
预编译不是万金油,CSS的好处在于简便、随时随地被使用和调试。预编译CSS步骤的加入,让咱们开发工做流中多了一个环节,调试也变得更麻烦了。
举个例子:原先咱们只须要在chrome/firebug里面找到相应的选择器,如.popup .popup-wrap .head
,源文件里面ctrl+F查找.popup .popup-wrap .head
就能够快速定位语句。如今咱们没法直接在预编译文件中查找,而须要寻找上下文,由于它在LESS中一般是这样被定义的:
.popup { .popup-wrap { .head { } } }
更大的问题在于,预编译很容易形成后代选择器的滥用。
曾经有一个观点是预编译能够解决样式覆写的问题,而我以为,正是预编译语言模糊了样式覆写的问题,而致使要解决样式相互覆写的问题时,问题已经变得规模庞大而难以解决。
举个极端的例子:
.popup { font-size: 12px; a { font-size: 13px; } .head { font-size: 18px; } } .informative { font-size: 14px; .head { font-size: 16px; } }
若是我有这么一个文档结构.popup.informative > .head > a
,须要a
的font-size
为17px
,你能快速想明白怎么改吗?叠罗汉式地再叠一层?仍是再糊一层墙皮,加一行样式?仍是干脆用!important
轰炸一番?
所以,实际项目中衡量预编译方案时,仍是得想一想,比起带来的额外维护开销,预编译有没有解决更大的麻烦。