CSS没有变量?不要诬蔑我们大CSS好不?就像ES一样,你说JS没有模块,ES6给你整一个出来,而在这之前就已经有相关的库出来了。CSS也一样,你说CSS没有变量,CSS3就给你一个var(),变量你值得拥有!
// 语法
// <custom-preperty-name> 自定义属性名
// <declaration-value>声明值(回退值)
// var( <custom-preperty-name>, <declaration-value>? )
:root {
--main-bg-color: pink;
}
body {
background-color: var(--main-bg-color, blue);
}
它也同ES6一样存在浏览器未部署不兼容的情况,即便它给了var()来打造变量,它仍旧显得很笨重!我提一个组件样式,为了避免样式冲突每次就得在前面加上一个组件唯一标识,就像这样:
.my-content article h1 { color: #333 }
.my-content article p { margin-bottom: 1.4em }
.my-content aside { background-color: #EEE }
得亏CSS扩展语言出现了,它为CSS引入了变量、混合器等等语法,让CSS得到模块化发展。CSS扩展语言大体上差不多,具体使用哪个语言来工作取决于开发者个人喜好,这里以Sass/SCSS举例。先说下这两位的区别,SCSS 是 Sass 3 引入新的语法,其语法完全兼容 CSS3,并且继承了 Sass 的强大功能。也就是说,任何标准的 CSS3 样式表都是具有相同语义的有效的 SCSS 文件。另外,SCSS 还能识别大部分 CSS hacks(一些 CSS 小技巧)和特定于浏览器的语法,例如:古老的 IE filter 语法。
.my-content {
article {
h1 { color: #333 }
p { margin-bottom: 1.4em }
}
aside { background-color: #EEE }
}
这样感觉就好多了,层级结构清晰,编译后就达到人工手写的样子。Sass也可以配合CSS选择器:
article {
~ article { border-top: 1px dashed #ccc }
> section { background: #eee }
dl > {
dt { color: #333 }
dd { color: #555 }
}
}
Sass的结构是呈父子级关系,有时需要引用同级(&):
article a {
color: blue;
body.ie & { color: green }
&:hover { color: red }
}
如果你感觉CSS属性有时候也挺烦躁的,可以使用属性嵌套,把属性名从中划线的地方断开,紧跟{}块。
// 这个例子不恰当,CSS本身可以简写
nav {
border: {
style: solid;
width: 1px;
color: #ccc;
}
}
// 编译后
nav {
border-style: solid;
border-width: 1px;
border-color: #ccc;
}
// 属性简写
nav {
border: 1px solid #ccc {
left: 0px;
right: 0px;
}
}
// 编译后
nav {
border: 1px solid #ccc;
border-left: 0px;
border-right: 0px;
}
Sass赋予CSS模块的能力,开发者可以将变量单独放在一些文件来方便自定义样式,可以根据需求分出不同的文件。这时就需要用到@import,CSS不常用的一个特性。通常会只想生成少数几个css文件来减少请求,Sass有一个特殊的约定:文件名以下划线开头。这样Sass就不会在编译时单独编译这个文件输出CSS,而只把这个文件导入,@import也不需要写全名。
// themes/_night-sky.scss
@import "themes/night-sky";
假如你定义了一个变量的文件来供使用者改变里面的默认值,然而反复声明一个变量只有最后一处会有效覆盖前边的值,这时需要!default。
$link-color: blue;
$link-color: red;
a {
color: $link-color; /* red */
}
// 修改:
$link-color: blue !default;
@import还允许写在CSS规则内,Sass会将局部文件的CSS规则插入到导入的位置:
// _blue-theme.scss
aside {
background: blue;
color: white;
}
// import
.blue-theme {@import "blue-theme"}
// 编译后
.blue-theme {
aside {
background: blue;
color: #fff;
}
}
因为Sass完全兼容CSS,所以它支持原生的@import,如果要导入原生CSS,须将后缀.css改为.scss再导入。
CSS的样式通常是给开发者内部的样式说明并不希望浏览者能看到,Sass提供了静默注释/* .... */。
为了使得网站的风格得到统一,那么统一使用变量处理是非常不错的选择,但是当样式越来越复杂,有一大段的样式要重用,独立变量就没办法了。这时需要混合器@mixin,如border-radio的兼容:
// @mixin
@mixin rounded-corners {
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
}
// @include
.notice {
background-color: green;
border: 2px solid #00aa00;
@include rounded-corners;
}
// 编译后
.notice {
background-color: green;
border: 2px solid #00aa00;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
}
那么什么时候使用@mixin呢?当不断重复使用一段样式,尤其是这段样式本身是一个逻辑单元。@mixin可以嵌套css规则,还可以进行传参及缺省参数:
// @mixin
@mixin rounded-corners($value:5px) {
-moz-border-radius: $value;
-webkit-border-radius: $value;
border-radius: $value;
}
// @include
.notice {
background-color: green;
border: 2px solid #00aa00;
@include rounded-corners(15px);
}
// 编译后
.notice {
background-color: green;
border: 2px solid #00aa00;
-moz-border-radius: 15px;
-webkit-border-radius: 15px;
border-radius: 15px;
}
增加代码的复用的另一个方法就是继承@extend:
.error {
border: 1px solid red;
background-color: #fdd;
}
.seriousError {
@extend .error;
border-width: 3px;
}
继承和混合器的区别:继承是基于类建立在语义关系上;混合器是展示性样式的重用。在Sass里,它们实际给人的感觉没有太大差别,用哪一个最后效果都一样,直观感受有差别。比如上面的.error,然后下面对不同的错误类进行细化,形成一种递进的关系,继承比混合器更适合。
(小声嘀咕:蛮喜欢Less的混合器写法,没有那么多的命令。)
这儿提到继承和混合,顺便说一下在面向对象的编程语言中,继承(Inheritence)和混入(Mixin)之间的区别。
继承描述了一个对象是什么,而混入描述了这个对象能做什么。比如柯基犬属于犬科动物类,犬科动物又属于动物类。将拥有共性的属性、行为的事物抽象归为一体就是父类,子类拥有父类的共性,这就是继承。柯基犬会吃,人也会吃,多啦A梦也会吃。多啦A梦还拥有飞的技能,小鸟也会飞,飞机也能飞。它们归属于不同的类,拥有一种共性行为,定义这些行为然后赋予拥有这些行为的对象,这就是混入。
好了,CSS扩展语言就说到这儿,具体的全看技术选型。