Sass 的用法

优质
小牛编辑
125浏览
2023-12-01

在这一章中,我将分享在我项目中每天使用到的一些Sass的特性。我还特别为这本书建立了一个虚拟项目来保证我们谈论的Sass的功能是在一个真实环境中进行的。这个项目就叫做Sasquatch Records–一个很简单的专注于神话,晦涩难懂的,牲畜类等超自然音乐风格的唱片公司网站。

Sass for Web Designers

Sasquath Records是一个我用来展示Sass例子的虚拟网站。

对于理清创建的一个复杂的样式表来说,Sass的能力是具有压倒性优势的。因为有许多可能性需要我们处理,我想要指出这个恰恰是Sass对于网站设计者来说最有价值的部分,而且还非常容易的就可以加入到你的工作流程中。

嵌套规则

使用Sass,你可以把重复的选择器隔离出去,将新的CSS规则嵌套到重复的选择器中。CSS嵌套的结构可以反映标签的结构。

例如,下面是Sasquath Records头部标签结构的主要部分:

<header role="banner">
    <div>
        <img src="http://www.w3cplus.com/preprocessor/logo.png" alt="Sasquatch Records" />
    </div>
    <h1>Sasquatch Records</h1>
    ...
</header>

当写Scss的时候,我可以对照着元素的嵌套关系,让Sass建立一个完整的选择器链。我个人喜欢在嵌套的选择器前放一个空行,让嵌套的CSS和父层的CSS属性保持同样的缩进:

header[role="banner"] {
    margin: 20px 0 30px 0;
    border-bottom: 4px solid #333;
    #logo {
        float: left;
        margin: 0 20px 0 0;
        img {
            display: block;
            opacity: .95;
        }
    }
    h1 {
        padding: 15px 0;
        font-size: 54px;
        line-height: 1;
        font-family: Jubilat, Georgia, serif;
        font-weight: bold;
    }
}

上面的代码会被编译成:

header[role="banner"] {
    margin: 20px 0 30px 0;
    border-bottom: 4px solid #333;
}
header[role="banner"] #logo {
    float: left;
    margin: 0 20px 0 0; 
}
header[role="banner"] #logo img {
    display: block;
    opacity: .95;
}
header[role="banner"] h1 {
    padding: 15px 0;
    font-size: 54px;
    line-height: 1;
    font-family: Jubilat, Georgia, serif;
    font-weight: bold;
}

Sass通过嵌套的层级关系来简化选择器中重复出现的每个元素。当然,在使用嵌套的时候也要非常小心。有时你不需要这么冗长的选择器链,并且过多的嵌套会造成可读性的障碍。层级深度只要几个就好,就像上面的例子一样,只为指定模块书写样式声明就可以了,Sass的嵌套会大大的节约你的时间。

嵌套命名空间的性能

除了嵌套规则之外,在Sass中你还可以将样式属性中共同的命名空间部分提取出来共享(例如:font-family,font-size,font-weight等等)。就像下面这样:

header[role="banner"] h1 {
    padding:15px 0;
    font: {
        size: 54px;
        family: jubilat,georgia,serif;
        weight: bold;
    }
    line-height: 1;
}

编译之后:

header[role="banner"] h1 {
    padding:15px 0;
    font-size: 54px;
    font-family: jubilat,georgia,serif;
    font-weight: bold;
    line-height: 1;
}

同样,在text这个命名空间中有很多属性。我们可以使用Sass的嵌套来节省一些重复的输入:

text: {
    transform: uppercase;
    decoration: underline;
    align: center;
}

background前缀也是一个很好的例子:

background: {
    color: #ea4c89;
    size: 16px 16px;
    image: url(sasquatch.png);
    repeat: no-repeat;
    position: top left;
}

在Sass中,嵌套就意味着减少输入,样式块对应当前选择器(或属性的公共部分)采用缩进格式。这个概念对每一个写CSS的人来说都是很容易理解的,跨度并不大。

使用&符号来代替父层的选择器

和嵌套规则和属性一脉相承的是,Sass还添加了一个使用&这个特殊占位符替代当前父层选择器的的功能。

例如,在一个链接的声明里面,我们可以添加鼠标移动上去(hover)的样式覆盖原来这个链接的颜色和边框的颜色。

a {
    font-weight: bold;
    text-decoration: none;
    color: red;
    border-bottom: 2px solid red;
    &:hover {
        color: maroon;
        border-color: maroon;
    }
}

在这个a标签的例子中,&符号插入到了父选择器中,编译之后就如下所示:

a {
    font-weight: bold;
    text-decoration: none;
    color: red;
    border-bottom: 2px solid red;
}
a:hover {
    color: maroon;
    border-color: maroon;
}

还有另外一个用&标签替代父选择器加上不同的class名触发不同的样式展示的例子:

li a {
    color: blue;
    &.alert {
        color: red;
    }
    &.success {
        color: green;
    }
}

编译之后:

li a {
    color: blue;
}
li a.alert {
    color: red;
}
li a.success {
    color: green;
}

在有指定class插入覆盖当前样式的情况下,&也是非常有用的。比如,我们打比方说,整个网站的主要章节中的段落的样式是统一的,但我们想要在一些特殊页面中让样式有一些轻微的改变。我们给body标签添加class,然后我们可以用&标签加在指定的class后面来覆盖之前的主样式:

section.main p {
    margin: 0 0 20px 0;
    font-size: 18px;
    line-height: 1.5;
    body.store & {
        font-size: 16px;
        line-height: 1.4;
    }
}

编译之后:

section.main p {
    margin: 0 0 20px 0;
    font-size: 18px;
    line-height: 1.5;
}
body.store section.main p {
    font-size: 16px;
    line-height: 1.4;
}

在store页面(或者其他带有<body class=”store”>的页面),段落的文字和行间距会比其他页面的要小一些。但是并没有将样式全部重新写,我们嵌套着使用&符号创建了父层的选择器,让Sass补全整个选择器。这样我们就再一次的节省了我们的时间,并且让有关联的规则都放在了同一个组里。

Sass中的注释

Sass除了支持标准样式表中的单行注释,还支持多行注释。

比如:

/* This is a multi-line comment that will 
appear in the final .css file. */

你可以通过在注释的第一个字符插入一个!来确保重要的注释(版权信息,作者,补丁的说明等等)出现在输出风格为压缩样式中:

/*! This is a multi-line comment that will 
appear in the final .css file. Even in compressed style. */

单行注释在每行的开始使用//前缀,并且不包含在最后编译出来的css文件中,所以你可以安全的使用他们写一些私人的注释:

// This is a single-line comment.
// Single-line comments are removed from the .css file.
// So you can say whatever you'd like here.
// Confession: I genuinely enjoy listening to ABBA.
// And Hall & Oates.

除了可以隐藏你在音乐中怪异的品味外,单行注释对于内部开发团队中的成员看别人写的SCSS代码提供了很多便利。注释可以频繁并详细的描述,不用担心会输出到最终的CSS中导致其文件大小变得臃肿。

变量

Sass有很多非常有用的特性,可以使我们的前端开发变得更轻松。但如果让我在众多特性中选择一个最有用的话,我首选变量这个特性。

我们经常在样式中重复书写一些东西。颜色,字体,背景图片,宽度等等。如果有一个需求,要求在一个很大规模的文档中查找和替换上面提到的颜色,字体,背景图片等等。这时变量就可以很简单轻松的维护上面说的情况。

Sass中变量的定义就像一个整齐的CSS规则前面加上$符号:

$color-main: #333;
$color-light: #999;
$color-accent: #ea4c89;
$font-sans: "Proxima Nova", "Helvetica Neue", Helvetica, Arial, sans-serif;
$font-serif: Jubilat, Georgia, serif;

一旦定义过,他们就可以在声明中调用:

body {
    padding: 0 8%;
    font-family: $font-sans;
    font-size: 100%;
    color: $color-main;
    background: #fff url(../img/bg.jpg) repeat-x -80% 0;
}

在CSS输出文件中Sass将会用变量的值进行替换:

body {
    padding: 0 8%;
    font-family: "Proxima Nova", "Helvetica Neue", Helvetica, Arial, sans-serif;
    font-size: 100%;
    color: $color-main;
    background: #fff url(../img/bg.jpg) repeat-x -80% 0;
}

使用Sass变量,可以实现将重复的代码立刻进行大规模的整体改变,所以你并不需要在整个文件中逐个查找替换。

做一个使用变量的样式规范

Jina Bolton写了一篇很棒的关于Sass变量怎么帮助我们创建一个颜色调色板样式规范的文章。Jina这样写道:

为了保持我们样式规范有意义,这个规范文档需要仅在同一项目中的管理员层面内部制定。在我们显示颜色的调色板的旁边注上相关的Sass变量名,如果我们已经建立了样式规范并在这个应用中使用了相同的前端代码,我们可以参考调色板中的变量名来使用相同的变量。当我们修改这些变量的值的时候,调色板也会自动更新(图3.2)。

Sass for Web Designers

图3.2 Jina Bolton使用Sass创建的样式规范。

比起创建过时的静态样式规范,使用Sass变量定义调色板意味着所有人都可以更新维护样式规范。

使用样式规范的变量像是一个函数,Jina又继续深入讨论了用Sass的颜色函数创建调色板中的变量。

例如,对于Sasquatch Records网站来说有一个很小的调色板,使用单行注释就可以注明每个颜色因为这么不重要的信息也不会输出到CSS中:

$color-main: #333;       //black
$color-light: #999;      //grey
$color-accent: #ea4c89;  //pink

接下来,使用Sass中的darken或者lighten颜色函数,我们可以生成基于调色板的不同的颜色深浅。

我们可以让粉色变暗30%:

section.secondary{
    background: darken($color-accent,30%);
}

Sass for Web Designers

当编译完成后,Sass将计算出原始的粉色降低30%后的值转换成16进制的色值:

section.secondary{
    background: #8d1040;
}

我们也可以让颜色变亮30%:

section.secondary{
    background: lighten($color-accent,30%);
}

Sass for Web Designers

编译之后:

section.secondary{
    background: #fad5e3;
}

CSS变量怎么样?

Sass(一般CSS预处理器也一样)非常好的一点是它提供了一个准备加入到标准中的特性测试范围。换句话说,Sass可以小步快跑,部署CSS还没有支持的特性。如果这些特性证明已经可以发布了,他们就会进入到正式的环境中。

变量就是很好的例子,可能也是CSS预处理器中使用最多的特性。通过运用Sass和LESS,包含的变量就好像是官方css的特性一样,被大力支持。当前W3C草案“CSS变量模型级别1”正在被开发,最新的WebKit内核已经对变量进行了支持。这就意味着对于原生CSS变量的支持已经准备好了。

不幸的时,在写这篇文章的时候发现,CSS变量的语法和Sass不同,没有Sass那样优雅或者易于理解掌握。例如,对文档中的root元素进行CSS变量的定义:

:root{
    var-color-main: #333;
}

在下面的声明当中使用变量:

#main p {
    color: var(color-main);
}

建议使用一个var的前缀来定义变量,使用var(variable-name)的语法来取变量的值。这有一点蠢而且容易让人迷惑,但是这是一个过程,在这个过程中有很多人也在呼吁使用类似Sass的$foo的语法。希望这是一个最终的解决方法。

最重要的,浏览器的支持限制了WebKit的最新版本的发挥,总之CSS变量不能在生产环境中使用,也没有其他理由驻留在Sass中。

Mixins

让我们推进到我第二喜欢的Sass的特性:mixins。变量可以让你在整个样式表中定义和复用,mixins允许你定义和复用样式块。你可以使用mixins定义一组样式,并在在你需要的时候就可以调用它,而不需要在各种声明中一次又一次输入相同的规则。

举个例子,让我们在Sasquatch Records网站上创建一小段mixin的标题样式(图3.3)。这些标题可以出现在页面中的多个位置,样式是完全一样的,这时用mixins是非常合适的。

Sass for Web Designers

图3.3 在Sasquatch Records网站上共享标题的样式。

首先,我们会在.scss文件的头部用Sass的@mixin指令定义一个mixin。我把它命名为title-style,在里面定义margin和字体的样式规则:

@mixin title-style {
    margin: 0 0 20px 0;
    font-family: $font-serif;
    font-size: 20px;
    font-weight: bold;
    text-transform: uppercase;
}

一旦定义完,我们就可以用@include指令在任何地方调用这个mixin插入样式。

在Sasquatch网站上,我们已经有了一段定义了页面主要样式的规则,我们想要这个样式加入到所有的<h2>标签:

section.main h2 {
    @include title-style;
}

编译完:

section.main h2 {
    margin: 0 0 20px 0;
    font-family: $font-serif;
    font-size: 20px;
    font-weight: bold;
    text-transform: uppercase;
}

但是我们也想要侧边栏的<h3>标签添加一模一样的样式,所以,我们可以调用同一个mixin编译相同规则:

section.secondary h3 {
    @include title-style;
}

这样做让我们避免了给两个标题标签添加class后,还要重复书写共享的样式。

Mixins也可以包含额外的规则:

section.secondary h3 {
    @include title-style;
    color: #999;
}

编译后

section.main h3 {
    margin: 0 0 20px 0;
    font-family: $font-serif;
    font-size: 20px;
    font-weight: bold;
    text-transform: uppercase;
    color: #999;
}

共享的样式可以从mixins中抽离出来,你仍然可以在mixins后覆盖或者增加一些额外的样式。太给力了。

Mixin参数

当我们调用mixin指令时,mixin也可以接受参数传递。例如,我们添加一个指定的颜色参数给我们的title-style这个mixin。

在定义mixin式,指定一个变量参数放到父级形参位置:

@mixin title-style($color) {
    margin: 0 0 20px 0;
    font-family: $font-serif;
    font-size: 20px;
    font-weight: bold;
    text-transform: uppercase;
    color: $color;
}

调用mixin时,我们传一个色值给它,其他规则依旧:

section.main h2 {
    @include title-style(#c63);
}

编译后:

section.main h2 {
    margin: 0 0 20px 0;
    font-family: Jubilat, Georgia, serif;
    font-size: 20px;
    font-weight: bold;
    text-transform: uppercase;
    color: #c63;
}

多参数

你可以在mixin的定义中用逗号分隔传多个参数:

@mixin title-style($color, $background) {
    margin: 0 0 20px 0;
    font-family: $font-serif;
    font-size: 20px;
    font-weight: bold;
    text-transform: uppercase;
    color: $color;
    background: $background;
}

下面的例子中,这个mixin被两个不同的选择器调用,传递了不同的颜色和背景参数:

section.main h2 {
    @include title-style(#c63, #eee);
}
section.secondary h3 {
    @include title-style(#39c, #333);
}

上面的例子编译后:

section.main h2 {
    margin: 0 0 20px 0;
    font-family: Jubilat, Georgia, serif;
    font-size: 20px;
    font-weight: bold;
    text-transform: uppercase;
    color: #c63;
    background: #eee;
}
section.secondary h3 {
    margin: 0 0 20px 0;
    font-family: Jubilat, Georgia, serif;
    font-size: 20px;
    font-weight: bold;
    text-transform: uppercase;
    color: #39c;
    background: #333;
}

你现在明白mixins有多灵活了吧,通过传递参数,公用的样式规则可以有一些轻微的不同来适应不同的场景。

定义默认的参数

当你使用mixin的参数时,定义一个经常使用的值作为默认参数是很方便的。如果那样做了,你只需要简单的调用mixin,不用传递参数,如果有默认的值,会把这个值传递过去。

@mixin title-style($color, $background: #eee) {
    margin: 0 0 20px 0;
    font-family: $font-serif;
    font-size: 20px;
    font-weight: bold;
    text-transform: uppercase;
    color: $color;
    background: $background;
}

虽然我们在mixin中定义了一个默认的浅灰色的背景,我们还是可以传递一些不同的参数:

section.main h2 {
    @include title-style(#c63);
}
section.secondary h3 {
    @include title-style(#39c, #333);
}

再次编译后:

section.main h2 {
    margin: 0 0 20px 0;
    font-family: Jubilat, Georgia, serif;
    font-size: 20px;
    font-weight: bold;
    text-transform: uppercase;
    color: #c63;
    background: #eee;
}
section.secondary h3 {
    margin: 0 0 20px 0;
    font-family: Jubilat, Georgia, serif;
    font-size: 20px;
    font-weight: bold;
    text-transform: uppercase;
    color: #39c;
    background: #333;
}

另外,当你有多个默认参数在mixin中定义,你可以有选择的覆盖默认参数,而不需要全部重新定义。

就拿我们下面定义的$color和$background来说:

@mixin title-style($color: blue, $background: green) {
    margin: 0 0 20px 0;
    font-family: $font-serif;
    font-size: 20px;
    font-weight: bold;
    text-transform: uppercase;
    color: $color;
    background: $background;
}

如果我们想保留默认的颜色是蓝色,而只把背景色修改为粉色,我们只需要给背景色传递参数:

section.main h2 {
    @include title-style($background: pink);
}

编译后:

section.main h2 {
    margin: 0 0 20px 0;
    font-family: Jubilat, Georgia, serif;
    font-size: 20px;
    font-weight: bold;
    text-transform: uppercase;
    color: blue;
    background: pink;
}

在mixin中保存这些默认参数可以大大节省你的时间。

mixin非常适合使用CSS3

在CSS3中使用带参数的mixins是一个亮点,因为我们经常要在整个样式表中重复写一些浏览器的私有前缀来让浏览器识别这个样式,例如圆角,阴影,渐变,变形等。因为在整个设计中,这些共享的重复的样式非常多,而且属性值可能会不太一样,Sass处理这些CSS3是一件再简单不过的事了。不记得创建渐变的CSS的语法?没关系,用mixin就搞定了!

圆角border-radius

下面是一个兼容所有浏览器的用CSS3处理圆角样式的例子,只需要给圆角传一个值即可:

@mixin rounded($radius) {
    -webkit-border-radius: $radius;
     -moz-border-radius: $radius;
          border-radius: $radius;
}

我们在页面中任意地方需要用到圆角,只用调用上面这个mixin就可以了:

ol.slats li a img {
    float: left;
    margin: 0 10px 0 0;
    padding: 4px;
    border: 1px solid #ddd;
    @include rounded(3px);
}
div.module {
    padding: 20px;
    background: #eee;
    @include rounded(10px);
}

编译后:

ol.slats li a img {
    float: left;
    margin: 0 10px 0 0;
    padding: 4px;
    border: 1px solid #ddd;
    -webkit-border-radius: 3px;
     -moz-border-radius: 3px;
          border-radius: 3px;
}
div.module {
    padding: 20px;
    background: #eee;
    -webkit-border-radius: 10px;
       -moz-border-radius: 10px;
    border-radius: 10px;
}

盒模型阴影box-shadow

下面是一个使用多参数的例子:用CSS3创建一个阴影的mixin,需要传递水平和垂直的偏移量,模糊的范围,还有颜色,4个参数:

@mixin shadow($x, $y, $blur, $color) {
    -webkit-box-shadow: $x $y $blur $color;
       -moz-box-shadow: $x $y $blur $color;
            box-shadow: $x $y $blur $color;
}

我们把这个mixin添加到之前的div.module的例子中,让这个阴影以垂直向下1px,2px的模糊范围,颜色为50%透明度的黑色呈现:

div.module {
    padding: 20px;
    background: #eee;
    @include rounded(10px);
    @include shadow(0, 1px, 2px, rgba(0,0,0,.5));
}

编译后:

div.module {
    padding: 20px;
    background: #eee;
    -webkit-border-radius: 10px;
       -moz-border-radius: 10px;
            border-radius: 10px;
    -webkit-box-shadow: 0, 1px, 2px, rgba(0,0,0,.5);
       -moz-box-shadow: 0, 1px, 2px, rgba(0,0,0,.5);
            box-shadow: 0, 1px, 2px, rgba(0,0,0,.5);
}

不需要一次又一次的在样式中书写浏览器私有前缀,只需要在一个地方写一次,就可以在你想使用的地方复用。

渐变 CSS3 gradients

CSS3渐变的语法让人非常厌烦。在各浏览器中的写法都不一样,不容易记忆,并且书写规范进化的进程非常快,强迫作者要不断更新他们的样式表。基于以上原因,Sass(特别是mixin)利用CSS3渐变做了一个可随时更新的小功能。当规范变更时,我们只需要在mixin中更新一次语法规范即可。

例如,我们往Sasquatch Records网站的tab页卡上添加一个线性渐变(图3.4)。为了保证渐变在大多数浏览器中可以显示,而且在不支持渐变的浏览器中显示纯色,我们需要全面的属性堆栈:

header nav[role="navigation"] ul li.active a {
    padding: 3px 8px;
    color: #fff;
    -webkit-border-radius: 4px;
       -moz-border-radius: 4px;
            border-radius: 4px;
    /* Fallback for sad browsers */
    background-color: #d42a78;
    /* Mozilla Firefox */
    background-image: -moz-linear-gradient(#ff70b1, #d42a78);
    /* Opera */
    background-image: -o-linear-gradient(#ff70b1, #d42a78);
    /* WebKit (Safari/Chrome 10) */
    background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #ff70b1), color-stop(1, #d42a78));
    /* WebKit (Chrome 11+) */
    background-image: -webkit-linear-gradient(#ff70b1, #d42a78);
    /* IE10 */
    background-image: -ms-linear-gradient(#ff70b1, #d42a78);
    /* W3C */
    background-image: linear-gradient(#ff70b1, #d42a78);
}

Sass for Web Designers

图3.4 利用mixin写的兼容浏览器的渐变

每一个创建由上到下渐变的私有前缀属性,都有相同的从开始的十六进制色值到结束的十六进制色值。用Sass的mixin,我们可以通过传递渐变颜色的变量给mixin来很简单的调用这些。谁能每次写渐变的时候都记得这些样式规则啊?下面做一些改变让我们更轻松一点吧。

首先我们建一个叫linear-gradient的mixin,在整个样式中把十六进制的色值提取出来,通过$from和$to两个变量将色值传递到样式代码中:

@mixin linear-gradient($from, $to) {
    /* Fallback for sad browsers */
    background-color: $to;
    /* Mozilla Firefox */
    background-image:-moz-linear-gradient($from, $to);
    /* Opera */
    background-image:-o-linear-gradient($from, $to);
    /* WebKit (Safari 4+, Chrome 1+) */
    background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, $from), color-stop(1, $to));
    /* WebKit (Chrome 11+) */
    background-image: -webkit-linear-gradient($from, $to);
    /* IE10 */
    background-image: -ms-linear-gradient($from, $to);
    /* W3C */
    background-image: linear-gradient($from, $to);
}

注意,我使用了变量$to的颜色来指定当浏览器不支持CSS渐变样式时,background-color的背景颜色。

非常感谢我们只用写这么折磨人的样式一次。现在,当我们想要创建一个简单的渐变的时候,我们就可以选择两个颜色传给mixin,剩下的Sass就帮我们做了。对于Sasquatch网站,tab页卡的样式声明如下:

&.active a {
    padding: 3px 8px;
    color: #fff;
    @include rounded(4px);
    @include linear-gradient(#ff70b1, #d42a78);
}

这不仅仅是可以接受的,这是有意义的!用英语好像是这么说。我可以复用这个片段,比如说一个蓝色按钮(图3.5),我就可以在另外一个选择器上不用写那么多复杂的渐变样式代码了。

button {
    padding: 5px 10px;
    color: #FFF;
    @include rounded(6px);
    @include linear-gradient(#42b3e2,#1a6798);
}

Sass for Web Designers

图3.5 利用mixin轻松写出带渐变的按钮。

正如你知道的,我们在这个简单的例子中使用了线性渐变,CSS渐变还包含了很多更复杂的情况,如多重渐变,径向渐变,多方向渐变等等。将上面提到的样式属性的公用部分摘出来添加到可复用的mixin中,Sass就也可以处理这些情况了。

创建一个mixin库

mixin是美好的因为它们可以让你一次书写到处使用。但我们经常会遇到跨项目时,要调用之前别的项目写过的mixin。你会希望找到你之前写过的公用CSS3属性样式,如box-shadow,渐变,CSS变形,清除浮动的样式,box-sizing,表单元素等等。你是不是也想一次书写,各个项目中到处使用呢?

@import

输入@import规则后,Sass被扩展允许导入多个Scss文件,编译后会把这些Scss文件合并成一个单独的css文件。这有几个现成的理由:

  • 单独一个CSS意味着更少的HTTP请求。提高了性能!
  • 变量可以在各自文件中定义,不用管布局和其他特殊页面的样式,需要的时候才导入。
  • 导入的SCSS文件可以包含其他项目共享和复用的mixin。

下面用@import做个练习。

我有一个mixins.scss的文件,里面已经导入了我所有的项目。在那个文件中我已经定义了一些我每个项目用到的公共的片段。下面就是mixins.scss中的例子:

@mixin rounded($radius) {
    -webkit-border-radius: $radius;
       -moz-border-radius: $radius;
            border-radius: $radius;
}
@mixin shadow($x, $y, $blur, $color) {
  -webkit-box-shadow: $x $y $blur $color;
     -moz-box-shadow: $x $y $blur $color;
          box-shadow: $x $y $blur $color;
}
@mixin shadow-inset($x, $y, $blur, $color) {
    -webkit-box-shadow: inset $x $y $blur $color;
       -moz-box-shadow: inset $x $y $blur $color;
            box-shadow: inset $x $y $blur $color;
}
@mixin transition($property) {
    -webkit-transition: $property .2s ease;
       -moz-transition: $property .2s ease;
         -o-transition: $property .2s ease;
            transition: $property .2s ease;
}
@mixin box-sizing {
-webkit-box-sizing: border-box;
   -moz-box-sizing: border-box;
        box-sizing: border-box;
}
@mixin linear-gradient($from, $to) {
    /* Fallback for sad browsers */
    background-color: $to;
    /* Mozilla Firefox */
    background-image:-moz-linear-gradient($from, $to);
    /* Opera */
    background-image:-o-linear-gradient($from, $to);
    /* WebKit (Chrome 11+) */
    background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, $from), color-stop(1, $to));
    /* WebKit (Safari 5.1+, Chrome 10+) */
    background-image: -webkit-linear-gradient($from, $to);
    /* IE10 */
    background-image: -ms-linear-gradient($from, $to);
    /* W3C */
    background-image: linear-gradient($from, $to);
}

在我主样式的最上方(主样式指的是screen.scss),使用@import指令,把我定义了我所有的布局和其他指定的网站样式导入进来,以便使用mixins。我也在每个项目中导入一个复用的reset样式表(再次节省HTTP请求并且避免复制黏贴相同代码)和一个存放颜色,字体等变量的变量文件。(图3.6)。我也可以在其他样式表中导入相同的变量-比如,在同一项目的其他页面或章节中,使用同一个样式规范-里面也可以没有导入其他布局。

Sass for Web Designers

图3.6 使用@import命令合并大块的Scss文件到一个文件中。

// Import other files 
@import "reset.scss";
@import "variables.scss";
@import "mixins.scss"; 
// Site-specific styles 
.foo {
  …
}

当Sass编译生成screen.css文件的时候,它包含了@import进来的所有的文件。所以,你只需要下载单个文件,在这个文件中灵活的添加减少多个包含可复用代码的文件,这样做真的很方便。

compass框架

使用mixins,变量和@import,你可以建立你自己强大的CSS框架帮助你在开展新项目时节省大量开发时间。只用一行代码就可以替代复杂的CSS3堆栈和其他经常重复的片段,让你有更多的时间创建新的代码,减少讨论代码的时间。

使用Compass框架会将这种代码组织优势带入下一个阶段,Compass框架是Chris Eppstein(Sass核心成员并且是最好的一个)写的一个基于Sass开源的样式框架。Compass提供了很多预先写好的CSS片段,采用渐进增强的方式保持浏览器的兼容行。Compass可以做图片合并和简单的排版处理(图3.7)。

Sass for Web Designers

图3.7 Compass网站

我总是建议你创建自己的框架,因为这样会让你理解透彻自己的代码是干什么。但把其他框架作为学习经验的对象会发现别人写的框架非常便利-用别人写的框架建立项目增加效率。Compass也不例外。

Bourbon库

基于设计即是开发的想法,把许多mixin放到一个库中,起名Bourbon,恰巧,我还非常爱喝这个酒,并在酒中加上稍苦一些的味美斯酒还混合一些糖和水果(图3.8)。

Sass for Web Designers

图3.7 Bourbon网站

稍微google一下就会发掘出许多在GitHub上或个人站点上Sass作者分享的mixins,看完之后很有帮助。幸运的是,那些令人厌烦的,维护成本高德CSS3堆栈样式已经都用mixin封装好了,所以要利用论坛或社区的优势。

@extend

你以前是不是遇到过这种情况:除了少数几行属性不一样,其他属性完全一致,只不过class名不同。

就像下面这个例子一样。在页面顶部你有一个两种情况的警告消息框样式。一种是处理标准的警告(图3.9),第二种是处理位置的警告(图3.10)。这些样式除了背景色不一样,其他的完全一样。

Sass for Web Designers

图3.7 Sasquatch Records网站的两种警告样式。

传统的做法是,我们会创建一个基础的class,添加正常情况下警告的样式,然后再创建一个class,里面只写背景色,用第二个class的样式覆盖第一个class的背景色。

<h2 class="alert alert-position">This is a positive alert!</h2>

这两个class的样式如下:

.alert {
    padding: 15px;
    font-size: 1.2em;
    font-weight: normal;
    text-transform: uppercase;
    line-height: 1;
    letter-spacing: 3px;
    text-align: center;
    color: #fff;
    background: $color-accent;
    @include shadow(0, 1px, 2px, rgba(0,0,0,.5));
    @include rounded(10px);
}
.alert-positive {
    background: #9c3;
}

我们可以使用Sass中的@extend函数将所有公用这个样式的多个class“捆绑”到一起,而不是在标签上写额外的class来处理细微的差别。此外,我们还可以单独的给class中除去公用样式外添加额外的样式。

所以如果我们想使用@extend处理警告消息框的两种情况,我们只需要一个class即可:

<h2 class="alert-position">This is a positive alert!</h2>

然后使用@extend将h2.alert这个class中的样式包含进来,再额外添加一个background-color:

.alert-positive {
    @extend .alert;
    background: #9c3;
}

Sass会高效的编译扩展class:

.alert, .alert-positive {
    padding: 15px;
    font-size: 1.2em;
    font-weight: normal;
    text-transform: uppercase;
    line-height: 1;
    letter-spacing: 3px;
    text-align: center;
    color: #fff;
    background: #ea4c89;
    -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
        moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
            box-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
    -webkit-border-radius: 10px;
       -moz-border-radius: 10px;
            border-radius: 10px;
}
.alert-positive {
    background: #9c3;
}

用这种方法写CSS和开始手工写的是一样的,不过@extend语法会更快一些–在不涉及到清除这两个class之间通用的样式的时候。因为这样很容易就使你头大了。

使用@extend还可以简化我们的语义,class的定义应该是基于要表达的意义而不是外在表现。

多个@extends

你可以在一个声明中@extend多个class,将这些class的样式都“捆绑”到这个class中。

.alert {
    padding: 15px;
    font-size: 1.2em;
    text-align: center;
    background: $color-accent;
}
.important {
    font-size: 4em;
}
.alert-positive {
    @extend .alert;
    @extend .important;
    background: #9c3;
}

编译后:

.alert, alert-positive {
    padding: 15px;
    font-size: 1.2em;
    text-align: center;
    background: #ea4c89;
}
.important, .alert-positive {
    font-size: 4em;
}
.alert-positive {
    background: #9c3;
}

Sass再一次显示了组织代码的效率,首先将一组公用样式放在一起,然后使用逗号分隔选择器,最后为差别的样式再创建单个声明。

在@extend中使用占位符选择器

假使有一个class仅仅是作为被别的@extend调用的将会怎么样?换句话说,你可能创建了没有人调用的class。

输入占位符选择器,允许你定义一个实际不存在的class,在输出的CSS中也不会出现。你可以使用@extend来调用占位符。

现在来看一下下面这个练习。我们为定义按钮的样式块创建一个class。在Sass中定义占位符选择器就是在class名前缀的句号换成%。

%button {
    padding: 10px;
    font-weight: bold;
    background: blue;
    border-radius: 6px;
}

我们可以像之前那样用@extend来调用这个规则来设置其他的class。

.buy {
    @extend %button;
}
.submit {
    @extend %button;
    background: green;
}

Sass将会像extend一个class一样来编译,但%button占位符的样式不会单独出现在输出的CSS文件中。

.buy, .submit {
    padding: 10px;
    font-weight: bold;
    background: blue;
    border-radius: 6px;
}
.submit {
    background: green;
}

在创建可能用的到可能用不到样式块时,占位符选择器是非常有用的(例如,框架,样式规范,刚开始的模板),因为不调用占位符class就不会在编译好的文件中产生垃圾代码。

@extend和@mixin的对比

mixin会在每个调用它的声明中写入相同的规则,而@extend会创建多个用逗号分隔的选择器来共享同一段样式。当你在犹豫使用哪个的时候,要好好想想它们之间的不同。

比如,过度使用mixin会在每次Sass编译成CSS后将mixin的内容留在CSS文件中,导致CSS文件臃肿。如果你发现你自己在整个样式中一次又一次的使用了同一个mixin,那么你应该考虑这个mixin是否合适,是不是应该单独写成一个class,在页面的标签中使用。

不要过度使用 @extend

在两个class之间共享一段公用的样式代码,那么使用@extend是非常有效的,但需要小心,当过度使用时,CSS就会变得杂乱无章。在整个样式表中重复@extend同一个class会让样式表的声明变得很怪异。使用Sass的过程中,很容易忘记编译后的样式表最终展现和Sass输出到你的工作中是带有tab的格式是不一样的。

好的,你现在已经非常厉害了。我们的学习已经将Sass的基础部分都覆盖了:包括如何建立Sass,语法规则是什么样的,如何更贴合你现在的代码习惯,还有如何通过嵌套,变量,mixins和@extend 来使用核心的特性。

如果你想要深入的学习,你会发现Sass包含的不仅仅是这些。在下一章节中,我们会继续讨论Sass是如何利用媒体查询来帮助我们完成响应式设计的。让我们冒险尝试一下吧