Sass基础教程
Sass基础教程
Sass基础语法
使用变量
变量声明
/* 声明$nav-color变量 这种注释内容会出现在生成的css文件中 */
$nav-color: #abcdef;
nav {
$width: 100px; // 声明$width变量 静默注释 这种注释内容不会出现在生成的css文件中
width: $width;
color: $nav-color;
}
变量引用
$highlight-color: #abcdef;
.selected {
border: 1px $highlight-color solid;
}
看上边示例中的 $highlight-color 变量,它被直接赋值给 border 属性,当这段代码被编译输出CSS时, $highlight-color 会被 #abcdef 这一颜色值所替代。产生的效果就是给selected 这个类一条1像素宽、实心且颜色值为 #abcdef 的边框。
嵌套 CSS 规则
基础使用
css原始方式:
#content article h1 { color: #333 }
#content article p { margin-bottom: 1.4em }
#content aside { background-color: #eee }
sass嵌套方式:
#content {
article {
h1 { color: #333 }
p { margin-bottom: 1.4em }
}
aside { background-color: #eee }
}
父选择器的标识符 &
article a {
color: blue;
:hover { color: red }
}
这意味着 color: red 这条规则将会被应用到选择器 article a :hover , article 元素内链接的所有子元素在被 hover 时都会变成红色。
article a {
color: blue;
&:hover { color: red }
}
结果:
article a { color: blue }
article a:hover { color: red }
群组选择器的嵌套
在CSS里边,选择器 h1 、 h2 和 h3 会同时命中 h1 元素、 h2 元素和 h3 元素。与此类似, .button 、button 会命中 button 元素和类名为 .button 的元素。这种选择器称为群组选择器。群组选择器的规则会对命中群组中任何一个选择器的元素生效。
.button, button {
margin: 0;
}
css写法:
.container h1, .container h2, .container h3 { margin-bottom: .8em }
sass写法
.container {
h1, h2, h3 {margin-bottom: .8em}
}
子组合选择器和同层组合选择器: > 、 + 和 ~
>
article section { margin: 5px }
article > section { border: 1px solid #ccc }
上例中,第一个选择器会选择 article下的所有命中 section 选择器的元素。第二个选择器只会选择 article 下紧跟着的子元素中命中section 选择器的元素。
+
同层相邻组合选择器 + 选择 header 元素后紧跟的 p 元素:
header + p { font-size: 1.1em }
~
同层全体组合选择器 ~ ,选择所有跟在 article 后的同层 article 元素,不管它们之间隔了多少其他元素:
article ~ article { border-top: 1px dashed #ccc }
嵌套属性
在Sass中,除了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文件
使用Sass部分文件
当通过 @import 把Sass样式分散到多个文件时,你通常只想生成少数几个CSS文件。那些专门为 @import 命令而编写的Sass文件,并不需要生成对应的独立CSS文件,这样的Sass文件称为局部文件。对此,Sass有一个特殊的约定来命名这些文件。
此约定即,Sass局部文件的文件名以下划线开头。这样,Sass就不会在编译时单独编译这个文件输出CSS,而只把这个文件用作导入。当你 @import 一个局部文件时,还可以不写文件的全名,即省略文件名开头的下划线。举例来说,你想导入themes/_night-sky.scss
这个局部文件里的变量,你只需在样式表中写 @import "themes/night-sky";
。
局部文件可以被多个不同的文件引用。当一些样式需要在多个页面甚至多个项目中使用时,这非常有用。在这种情况下,有时需要在你的样式表中对导入的样式稍作修改,Sass有一个功能刚好可以解决这个问题,即默认变量值。
默认变量值
一般情况下,你反复声明一个变量,只有最后一处声明有效且它会覆盖前边的值。举例说明:
$link-color: blue;
$link-color: red;
a {
color: $link-color;
}
在上边的例子中,超链接的 color 会被设置为 red 。这可能并不是你想要的结果,假如你写了一个可被他人通过 @import 导入的Sass库文件,你可能希望导入者可以定制修改Sass库文件中的某些值。使用Sass的 !default
标签可以实现这个目的。它很像CSS属性中 !important
标签的对立面,不同的是 !default
用于变量,含义是:如果这个变量被声明赋值了,那就用它声明的值,否则就用这个默认值。
$fancybox-width: 400px !default;
.fancybox {
width: $fancybox-width;
}
在上例中,如果用户在导入你的Sass局部文件之前声明了一个 $fancybox-width
变量,那么你的局部文件中对 $fancybox-width
赋值 400px 的操作就无效。如果用户没有做这样的声明,则 $fancybox-width
将默认为400px 。
接下来我们将学习嵌套导入,它允许只在某一个选择器的范围内导入Sass局部文件。
嵌套导入
blue-theme.scss文件,内容如下:
aside {
background: blue;
color: white;
}
然后把它导入到一个CSS规则内,如下所示:
.blue-theme {@import "blue-theme"}
生成的结果跟你直接在 .blue-theme 选择器内写_blue-theme.scss文件的内容完全一样。
.blue-theme {
aside {
background: blue;
color: #fff;
}
}
原生的CSS导入
由于Sass兼容原生的CSS,所以它也支持原生的CSS @import
。尽管通常在Sass中使用@import
时,Sass会尝试找到对应的Sass文件并导入进来,但在下列三种情况下会生成原生的CSS @import ,尽管这会造成浏览器解析CSS时的额外下载:
- 被导入文件的名字以.css结尾;
- 被导入文件的名字是一个URL地址(比如http://sass-lang.com/stylesheets/application.css),由此可用谷歌字体API提供的相应服务;
- 被导入文件的名字是CSS的 url() 值。
这就是说,你不能用Sass的 @import 直接导入一个原始的CSS文件,因为Sass会认为你想用CSS原生的 @import 。但是,因为Sass的语法完全兼容CSS,所以你可以把原始的CSS文件改名为.scss后缀,即可直接导入了。
文件导入是保证Sass的代码可维护性和可读性的重要一环。次之但亦非常重要的就是注释了。注释可以帮助样式作者记录写Sass的过程中的想法。在原生的CSS中,注释对于其他人是直接可见的,但Sass提供了一种方式可在生成的CSS文件中按需抹掉相应的注释。
混合器
混合器中使用 @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;
}
Sass最终生成:
.notice {
background-color: green;
border: 2px solid #00aa00;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
}
何时使用混合器
利用混合器,可以很容易地在样式表的不同地方共享样式。如果你发现自己在不停地重复一段样式,那就应该把这段样式构造成优良的混合器,尤其是这段样式本身就是一个逻辑单元,比如说是一组放在一起有意义的属性。
判断一组属性是否应该组合成一个混合器,一条经验法则就是你能否为这个混合器想出一个好的名字。如果你能找到一个很好的短名字来描述这些属性修饰的样式,比如 rounded-corners 、fancy-font 或者 no-bullets ,那么往往能够构造一个合适的混合器。如果你找不到,这时候构造一个混合器可能并不合适。
混合器中的CSS规则
混合器中不仅可以包含属性,也可以包含CSS规则,包含选择器和选择器中的属性,例如:
定义no-bullets混合器
@mixin no-bullets {
list-style: none;
li {
list-style-image: none;
list-style-type: none;
margin-left: 0px;
}
}
使用no-bullets混合器
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解开嵌套规则时,用父规则中的选择器替代 & 。
给混合器传参
混合器并不一定总得生成相同的样式。可以通过在 @include 混合器时给混合器传参,来定制混合器生成的精确样式。当 @include 混合器时,参数其实就是可以赋值给CSS属性值的变量。
如果你写过JavaScript,这种方式跟JavaScript的 function 很像:
@mixin link-colors($normal, $hover, $visited) {
color: $normal;
&:hover { color: $hover; }
&:visited { color: $visited; }
}
当混合器被@include时,你可以把它当作一个CSS函数来传参。如果你像下边这样写:
a {
@include link-colors(blue, red, green);
}
Sass最终生成的是:
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
);
}
尽管给混合器加参数来实现定制很好,但是有时有些参数我们没有定制的需要,这时候也需要赋值一个变量就变成很痛苦的事情了。所以Sass允许混合器声明时给参数赋默认值。
默认参数值
为了在 @include
混合器时不必传入所有的参数,我们可以给参数指定一个默认值。参数默认值使用 $name: default-value
的声明形式,默认值可以是任何有效的CSS属性值,甚至是其他参数的引用,例如:
@mixin link-colors(
$normal,
$hover: $normal,
$visited: $normal
) {
color: $normal;
&:hover { color: $hover; }
&:visited { color: $visited; }
}
如果像下边这样调用: @include link-colors(red)
, $hover
和 $visited
也会被自动赋值为 red 。
混合器只是Sass样式重用特性中的一个。我们已经了解到混合器主要用于样式展示层的重用,如果你想重用语义化的类呢?这就涉及Sass的另一个重要的重用特性:选择器继承。
附录
/* Compass将CSS3变得容易了!
尤其是CSS3渐变*/
@import "compass/css3"
// 这个混入类让我们可以轻松地制造渐变
// 它会为我们挑选颜色,很好。
@mixin easy-gradient($bg, $alpha: false) {
@if ($alpha) {
$bg: rgba($bg, $alpha);
}
$top: lighten($bg, 5);
$bottom: darken($bg, 5);
@include background-image(
linear-gradient($top, $bottom)
)
}
nav {
margin: 20px { left: 0; right: 0 }
@include easy-gradient(#ccc);
a { color: blue; text-decoration: none }
}