前言
这几天一直都在研究 Sass/Scss,这次就把 Sass 基础使用方法整理发表出来。让想学习这方面知识的朋友可以多一份参考资料。毕竟现在这方面的资料特别的稀缺。
在这里贴出这两天研究 Sass 的小小成果:
《Sass开发 – Ruby安装出错解决办法:淘宝网镜像 RubyGems》
这一路走来着实不易,跌跌撞撞,辛酸事就不提了。我们还是继续来说 Sass 吧。这个不是教程,而是一个好的分享,如果你觉得好可收藏哦!
Sass文件的创建
要想开始编写 Sass 代码,你就先得创建相应的文件。Sass 有两种后缀名文件:一种后缀名为 .sass,不使用大括号和分号;另一种就是我们这里使用的 Scss 文件,这种和我们平时写的 CSS 文件格式差不多,使用大括号和分号。本文中所说的所有 Sass 文件都指后缀名为 .scss 的文件。在此也建议使用后缀名为 .scss 的文件,以避免 .sass 后缀名的严格格式要求报错。
Sass文件创建好了,现在我们马上进入主题。
使用变量
Sass 让人们受益的一个重要特性就是它为 CSS 引入了变量。你可以把反复使用的 CSS 属性值 定义成变量,然后通过变量名来引用它们,而无需重复书写这一属性值。或者,对于仅使用过一 次的属性值,你可以赋予其一个易懂的变量名,让人一眼就知道这个属性值的用途。
变量声明
/* Sass代码 */
$highlight-color: #0099CC;
这段代码的作用是 定义变量 $highlight-color 的值为 #0099CC 。任何可用于 CSS 属性值的赋值都可以作为 Sass 的变量值,如$basic-border: 1px solid black;
,或者以逗号分割的多个属性值,如$plain-font: "Myriad Pro",Myriad,"Helvetica Neue",Helvetica,"Liberation Sans",Arial
和sans-serif; sans-serif;
变量引用
变量设置了,现在我们来看看如何引用。与 CSS 属性不同,在 Scss 中定义的变量可以在 CSS 规则块定义之外存在。当变量定义在 CSS 规则块内,那么该变量只能在此规则块内使用。如果它们出现在任何形式的{…}块中(如@media
或者@font-face
块),情况也是如此,我们不妨把他们统称为局部变量;而如果变量声明在 CSS 规则之外,那么这个变量可以用到事个 Sass 文件,我们不妨把他们称为全局变量。
/* Sass代码 */
$nav-color: #09C;
nav {
$width: 100px;
width: $width;
color: $nav-color;
}
/*编译后*/
nav {
width: 100px;
color: #09C;
}
这段代码包含了两种变量的定义。CSS 规则内变量的定义及 CSS 规则外变量的定义。$nav-color: #09C;
为全局变量,而$width: 100px;
为局部变量。
凡是 CSS 属性的标准值(比如说1px或者bold)可存在的地方,变量就可以使用。CSS 生成时,变量会被它们的值所替代。这句话怎么理解呢,我们再来看看下面这个例子
/* Sass代码 */
$highlight-color: #09C;
.selected {
border: 1px solid $highlight-color;
}
/*编译后*/
.selected {border: 1px solid #09C;}
上面这个例子中的 $highlight-color 变量,它被直接赋值给 border 属性,当这段代码被编译输出 CSS 时,$highlight-color
会被#09C
这一颜色值所替代。
还有一种情况就是在声明变量时,变量值也可以引用其他变量。
/* Sass代码 */
$highlight-color: #09C;
$highlight-border: 1px solid $highlight-color;
.selected {
border: $highlight-border;
}
/*编译后 */
.selected {border: 1px solid #09C;}
补充:变量名用中划线还是下划线分隔;对于这个问题其实也没什么好研究的,因为这完全取决于你个人的喜好!
嵌套CSS 规则
相信 CSS 中选择器的多次重复书写早已让你烦透了。不用担心 Sass 为你提供非常方便快捷的方式。
/* Sass代码 */
#content {
article {
h1 { color: #333 }
p { margin-bottom: 1.4em }
}
aside { background-color: #EEE }
}
/* 编译后 */
#content article h1 {color: #333}
#content article p {margin-bottom: 1.4em}
#content aside {background-color: #EEE}
编译后的代码是你要写的 CSS,但是如果你是用 Sass 来书写代码,你就只需要书写上面那一段 Sass 代码就可以了,编译后就会自动输出下面这一段 CSS 样式了,这样是不是方便多了呢?!
sass 用了两步,一步步往里(子元素前面)塞,把#content
(父级)这个 id 放到 article 选择器(子级)和 aside 选择器(子级)的前边,然后,#content article
里边还有嵌套的规则,sass重复一遍上边的步骤,把新的选择器添加到内嵌的选择器前边。这样一层层往里套,最后就输入了编译后的代码。
一个给定的规则块,既可以像普通的 CSS 那样包含属性,又可以嵌套其他规则块。当你同时要为一个容器元素及其子元素编写特定样式时,Sass 这种天生的优势就可以发挥得淋漓尽致了。
/* Sass代码 */
#content {
background-color: #f5f5f5;
aside { background-color: #eee }
}
原理:容器元素的样式规则会被单独抽离出来,而嵌套元素的样式规则会像容器元素没有包含任何属性时那样被抽离出来。最后就输出了如下 CSS 样式
/* 编译后 */
#content {background-color: #f5f5f5}
#content aside {background-color: #eee}
Sass父选择器的标识符&
父选择器的标识符&常用于A链接hover上,我们还是来看下下面这段 Sass 代码输出的 CSS 样式是什么。
/* Sass代码 */
article a {
color: blue;
:hover {
color: red
}
}
/* 编译后 */
article a {color: blue;}
article a :hover{color: red}
细心的朋友可能看到了a
与:hover
之间是有一个空格的,这与a:hover
是完全不同的作用范围。上面编译后的这代码的作用是,article元素内A链接的所有子元素在被(鼠标悬浮)hover 时都会变成红色。这往往不是我们想要的效果,因为我们本意是给A链接本身添加 CSS 样式。这时候 Sass 这个特殊的选择器标识符就大有作为了,请看下面这段代码
/* Sass代码 */
article a {
color: blue;
&:hover {color: red}
}
当包含父选择器标识符的嵌套规则被打开时,它不会像后代选择器那样进行拼接,而是&被父选择器直接替换:
/* 编译后 */
article a {color: blue}
article a:hover {color: red}
父选择器标识符&还有另外一种用法,你可以在父选择器之前添加选择器,请看下面这段代码
/* Sass代码 */
#content aside {
color: red;
body.ie & { color: green }
}
/*编译后*/
#content aside {color: red};
body.ie #content aside { color: green }
Sass在选择器嵌套上是非常智能的,即使是带有父选择器的情况。当 Sass 遇到群组选择器(由多个逗号分隔开的选择器形成)也能完美地处理这种嵌套。
群组选择器的嵌套
如果你需要在一个特定的容器元素内对一个群组选择器定义样式,如在.container
内有h1、h2、h3、h4、h5....
这么多标签时,你需要重复写很多篇.container
,如果只有几个那倒没什么所谓,但是有时候情况往往不是那样。不过Sass已经为我们提供了一个方法来完成这样一事伟大的事,请看代码
/* Sass代码 */
.container {
h1, h2, h3 {margin-bottom: .8em}
}
/*编译后*/
.container h1, .container h2, .container h3 { margin-bottom: .8em }
对于内嵌在群组选择器内的嵌 套规则,处理方式也一样:
/* Sass代码 */
nav, aside {
a {color: blue}
}
/*编译后*/
nav a, aside a {color: blue}
与普通的 CSS 编写方式相比,只写一遍群组选择器大大减少了工作量,看上去代码简洁多了,但是 Sass 代码经编译后生成的 CSS 样式可能会很大,所以样式最好要尽可能的少用,因为这会降低网站的访问速度。
子组合选择器和同层组合选择器:>、+和~
> 子组合选择器,用于选择一个元素的直接子元素。
+ 同层相邻组合选择器,用于选择指定元素后紧跟的目标元素。
~ 同层全体组合选择器,与+类似,但是这个选择器是选择同级所有的目标元素。
我们用一个例子来感受一下他们的存在
/* Sass代码 */
article {
~ article { border-top: 1px dashed #ccc }
> section { background: #eee }
dl > {
dt { color: #333 }
dd { color: #555 }
}
nav + & { margin-top: 0 }
}
/*编译后*/
article ~ article { border-top: 1px dashed #ccc }
article > footer { background: #eee }
article dl > dt { color: #333 }
article dl > dd { color: #555 }
nav + article { margin-top: 0 }
嵌套属性
除了CSS 选择器,属性也可以进行嵌套,我还是来看看代码
/* Sass代码 */
nav {
border: {
style: solid;
width: 1px;
color: #ccc;
}
}
/*编译后*/
nav {
border-style: solid;
border-width: 1px;
border-color: #ccc;
}
对于属性的缩写形式,你甚至可以像下边这样来嵌套,指明例外规则:
/* Sass代码 */
nav {
border: 1px solid #ccc {
left: 0px;
right: 0px;
}
}
/*编译后*/
nav {
border: 1px solid #ccc;
border-left: 0px;
border-right: 0px;
}
Sass 嵌套规则除了减少你编写代码的量外,还有视觉上冲击(样式结构更加清晰,易于阅读和开发)。
导入SASS文件
和 CSS 的@import
对应 Sass 也有一个 @import 规则,他们的不同之处是和 CSS 的@import
是只有执行到@import
时,浏览器才会去下载其他的 CSS 文件,而 Sass 的@import
规则在性能方面表现更佳,Sass 的@import
规则在生成 CSS 文件时就把相关文件导入进来。这意味着所有相关的样式被归纳到了同一个 CSS 文件中,而无需发起额外的下载请求。使用 sass 的@import
规则并不需要指明被导入文件的全名。你可以省略.sass
或.scss
文件后缀。
使用SASS部分文件
当在一个Sass文件中通过@import
把其它的 Sass 样式文件引入时,通常是不需要被引入的 Sass 文件生成对应的独立 CSS 文件,这些被引入的 Sass 文件称为局部文件。为此,Sass 有一个特殊的约定来命名这些文件。即局部文件的文件名以下划线开头,如:themes/_night-sky.scss 但是你也可以不写下划线 @import “themes/night-sky”;
默认变量值
一般情况下,反复声明一个变量,只有最后一处声明有效且它会覆盖前面的值
/* Sass代码 */
$link-color: blue;
$link-color: red;
a {
color: $link-color;
}
但有时候会出现引入的 Sass 局部文件(引入的 Sass 文件),在你的 Sass 文件定义的变量(Sass 局部文件已有的变量)之后这个情况,由上面这个例子我们知道,在 Sass文件中声明的变量会被Sass 局部文件中的变量覆盖了,这个往往不是你想要的,你想在Sass文件定义的变量起作用,不用担心,Sass 里的!default
标签可以帮到你,我们先来看看下面这一段代码
/* Sass代码 */
$fancybox-width: 400px !default;
.fancybox {
width: $fancybox-width;
}
在上例中,如果在导入Sass 局部文件之前声明了一个$fancybox-width
变量,那么局部文件中对$fancybox-width
赋值500px
的操作就无效。如果在 Sass 文件中没有做这样的声明,则 $fancybox-width 将默认为500px。
嵌套导入
sass允许@import
命令写在 css 规则内,成对应的 css 文件时,局部文件会被直接插入到 css 规则内导入它的地方。
/* Sass代码 */
aside {
background: blue;
color: white;
}
导入到CSS文件
.blue-theme {@import "blue-theme"}
//生成的结果跟你直接在.blue-theme选择器内写_blue-theme.scss文件的内容完全一样。
.blue-theme {
aside {
background: blue;
color: #fff;
}
}
你不能用 Sass 的@import
直接导入一个原始的 css 文件,因为sass会认为你想用 CSS 原生的@import
。但是,因为 Sass 的语法完全兼容CSS,所以你可以把原始的 CSS 文件改名为 .scss 后缀,即可直接导入了。
静默注释
以//开头的注释,在编译输出的 CSS 文件中不显示。
以/*….*/开头的注释,在编译输出的 CSS 文件中会得到显示。
/* Sass代码 */
body {
color: #333; // 这种注释内容不会出现在生成的css文件中
padding: 0; /* 这种注释内容会出现在生成的css文件中 */
}
/*编译后*/
body {
color: #333;
padding: 0;
/* 这种注释内容会出现在生成的css文件中 */ }
还有一种情况
当注释出现在原生 CSS 不允许的地方,如在 CSS 属性或选择器中时,/*….*/可以在编译输出 CSS 文件时被抹去。
/* Sass代码 */
body {
color /* 这块注释内容不会出现在生成的css中 */: #333;
padding: 1 /* 这块注释内容也不会出现在生成的css中 */ 0;
}
/*编译后*/
body {
color: #333;
padding: 1 0;
}
混合器
混合器作用跟变量作用是一样的,只不过混合器比变量强大一些,严格来说一个变量只能赋予一个值,如:颜色,字体等,而混合器却可以实现更加复杂的样式。说白了就是混合器里就是多个变量的集合。这个标识符给一大段样式赋予一个名字,这样你就可以轻易地通过引用这个名字重用这段样式。
@mixin rounded-corners {
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
}
可以在你的样式表中通过 @include 来使用这个混合器,放在你希望的任何地方。
/* Sass代码 */
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;
}
有了这个方法,重用的代码再也不需要码多次了。不过虽然好用,但也不能滥用。
混合器中的CSS规则
混合器中不仅可以包含属性,也可以包含css规则,包含选择器和选择器中的属性
@mixin no-bullets {
list-style: none;
li {
list-style-image: none;
list-style-type: none;
margin-left: 0px;
}
}
我们还是来看看下面这个例子
ul.plain {
color: #444;
@include no-bullets;
}
Sass 的 @include 指令会将引入混合器的那行代码替换成混合器里边的内容
ul.plain {
color: #444;
list-style: none;
}
ul.plain li {
list-style-image: none;
list-style-type: none;
margin-left: 0px;
}
混合器中的规则甚至可以使用 Sass的 父选择器标识符 &,用法跟之前提到过的一样。在这里就不费时间介绍了。
给混合器传参
我们可以通过给混合器传递参数来实现动态生成所需的样式
/* Sass代码 */
@mixin link-colors($normal, $hover, $visited) {
color: $normal;
&:hover { color: $hover; }
&:visited { color: $visited; }
}
当混合器被@include时,你可以把它当作一个css函数来传参。
/* Sass代码 */
a {
@include link-colors(blue, red, green);
}
/*编译后*/
a { color: blue; }
a:hover { color: red; }
a:visited { color: green; }
@include 混合器还是很体贴的,Sass 允许通过语法$name: value
的形式指定每个参数的值。这种方式的传参的好处就是,你不必再乎参数的顺序,并且还可以轻易的区分参数所应的值。
a {
@include link-colors(
$normal: blue,
$visited: green,
$hover: red
);
}
默认参数值
如果想在@include混合器时不必传入所有的参数,我们可以给参数指定一个默认值
@mixin link-colors(
$normal,
$hover: $normal,
$visited: $normal
)
{
color: $normal;
&:hover { color: $hover; }
&:visited { color: $visited; }
}
如果你给这传个参数@include link-colors(red)
,那么$hover
和$visited
也会被自动赋值为red
。
使用选择器继承来精简CSS
选择器继承可以通过@extend
语法实现。选择器的继承可以让 Sass 代码得到进一步的优化,选择器继承作用,继承另一个选择器定义的所有样式。
//通过选择器继承继承样式
.error {
border: 1px red;
background-color: #fdd;
}
.seriousError {
@extend .error;
border-width: 3px;
}
这里的继承跟上面说到的混合选择器很类似,但是继承却是混合选择器的升级版,为什么这么说,我们再来看看下面这一段代码
//.seriousError从.error继承样式
.error a{ //应用到.seriousError a
color: red;
font-weight: 100;
}
h1.error { //应用到hl.seriousError
font-size: 1.2rem;
}
这段代码是什么意思?这里想表达的是,我们给 error 元素里面的所有a链接也都定义了样式,此时继承的作用就显现出来了,继承了.error
的元素,同时也会继承 error 有关的组合选择器样式。并且会被.seriousError
以组合选择器的形式继承
//.seriousError从.error继承样式
.error a{ //应用到.seriousError a
color: red;
font-weight: 100;
}
h1.error { //应用到hl.seriousError
font-size: 1.2rem;
}
如上所示,在 class=”seriousError” 的 html 元素内的超链接也会变成红色和粗体。
继承的高级用法
在这里我们只是来分析下一些特殊的情况
6-2-1. 继承的是后代选择器
如果 .seriousError 继承了一个在形如#main .error
的.error
情况会怎么样呢?
/* Sass代码 */
#main .error {
border: 1px dashed red;
background-color: #fdd;
}
.seriousError {
@extend .error;
border-width: 3px;
}
/*编译后*/
#main .error, #main .seriousError {
border: 1px dashed red;
background-color: #fdd; }
.seriousError {
border-width: 3px; }
我们不难看出输出的.seriousError
前面也加了#main
作限制。
6-2-2. 后代选择器继承
/* Sass代码 */
.error {
border: 3px solid blue;
background-color: #09C;
}
#main .seriousError {
@extend .error;
border-width: 6px;
}
/*编译后*/
.error, #main .seriousError {
border: 3px solid blue;
background-color: #09C; }
#main .seriousError {
border-width: 6px; }
6-2-3. 后代选择器继承后代选择器
/*编译后*/
.web .error {
border: 5px dotted red;
background-color: #09C;
}
#main .seriousError {
@extend .error;
border-width: 2px;
}
/*编译后*/
.web .error, .web #main .seriousError, #main .web .seriousError {
border: 5px dotted red;
background-color: #09C; }
#main .seriousError {
border-width: 2px; }
细心的朋友可以已经看到其中的亮点了,这些继承方式不按常理出牌了。这可以也不是我们想要的结果,但是这也没办法,Sass 程序本身的处理机制就是这样,所以像上面这种继续我们最要不要在 Sass 开发过程当中使用,这是很危险的。
Sass研究心得:Sass 其实不是一个 新技术,他只是你书写 CSS 的一个新工具,自己个人感觉,现在 Sass 的用处还没真正的体现出来,如果只是说减少开发中所需要输入的代码量的话,我觉得很多编辑器也做得到,我想应该是我自己对 Sass 的精髓体会得还不够全面、深入。要不然为什么现在很多大公司都已经在用 Sass 了呢?
文章首发于云库前端 http://yunkus.com ,如有什么问题可以在这里留言或者到我的个人博客中留言交流。