CSS SASS 和 Compass 指南

lilu · 2012年07月18日 · 最后由 yunkus 回复于 2015年10月15日 · 58706 次阅读

前一段写的一篇,原载于我自己的blog ,算一个简单的介绍吧,可能有一些错漏,请多包涵:)

CSS 预处理器

CSS 预处理器 (CSS Preprocessor),是一种构架于 css 之上的高级语言,可以通过脚本编译生成 CSS 代码,其目的是为了让 CSS 开发者的工作更简单有趣,当前已经进入了较为成熟的阶段,基本上新的 web 开发项目大都已普遍使用。

现在最主要的选择有:

  • SASS 2007 年诞生,最早也是最成熟的 CSS 预处理器,拥有 ruby 社区的支持和 compass 这一最强大的 css 框架,目前受 LESS 影响,已经进化到了全面兼容 CSS 的 SCSS。
  • LESS 2009 年出现,受 SASS 的影响较大,但又使用 CSS 的语法,让大部分开发者和设计师更容易上手,在 ruby 社区之外支持者远超过 SASS,其缺点是比起 SASS 来,可编程功能不够,不过优点是简单和兼容 CSS,反过来也影响了 SASS 演变到了 SCSS 的时代,著名的 Twitter Bootstrap 就是采用 LESS 做底层语言的。
  • Stylus,2010 年产生,来自 Node.js 社区,主要用来给 Node 项目进行 CSS 预处理支持,在此社区之内有一定支持者,在广泛的意义上人气还完全不如 SASS 和 LESS。

我较为推崇的组合是,SASS+Compass+Twitter Bootstrap+bootstrap-sass,这一组合能够获得最好的底层语言 SASS,最好的框架 Compass,和 Bootstrap 提供的最强大的 UI 组件库 (被 bootstrap-sass 翻译成 SASS 的风格)。

下面就对 SASS 的常用要素做一简单介绍,大部分例子来自 SASS 设计者 Hampton Catlin 的著作Pragmatic Guide to Sass,本文不涉及安装过程,命令行工具,和其他 web 开发框架 (比如 Rails) 的结合,早期非 SCSS 的语法等内容,想了解更多的朋友可深入阅读上边这本书。


嵌套 (nesting)

/*CSS选择器(Selector)经常要重复class,id和element的名称*/
.infobox {width: 200px;}
.infobox .message {border: 1px solid red;}
.infobox .message > .title {color: red;}
//SASS可以让选择器嵌套,做到DRY
.infobox {
    width: 200px;
    .message {
        border: 1px solid red;
        > .title {color: red;}
    }
}

对于某些需要引入父选择器名称的情况,SASS 使用&代替

/*CSS会让同样元素的样式变得分散*/
.infobox {color: blue;}
.user .infobox {color: gray;}
.message {color: gray;}
.message.new {color: red;}
//SASS可以让他们在一起
.infobox {
    color: blue;
    .user & {color: gray;}
}
.message {
    color: gray;
    &.new {color: red;}
}

对于当前做跨平台 web 开发来说,@media非常常用,而 SASS 的嵌套会区别对待

/*CSS*/
.main {
    font-size: 15px;
}    

@media screen and (max-width: 320px) {
    .main {
        font-size: 35px; 
    }
}
//SASS让同样的选择器在不同media条件下的样式在一起
.main {
    font-size: 15px;
    @media screen and (max-width: 320px) {
        font-size: 35px; 
    } 
}

变量 (variables)

变量是编程语言的基石,掌握变量的定义和使用,是 SASS 编程的起点。

/*CSS中同样的值不得不重复很多次*/
body {background: #336699;}
body #wrapper {
    width: 300px;
    background: white;
    border: #eee; 
}
body #wrapper h1 {color: #336699;}
//SASS有了变量,只需要改一次,而且往往相关值一起定义的,方便查找
//可以定义全局变量
$primary_color: #369;
$secondary_color: #eee;

body {
    //也可以定义局部变量
    $page_width: 300px;

    background: $primary_color;
    #wrapper {
        width: $page_width;
        background: white;
        border: $secondary_color;
        h1 {color: $primary_color; } 
    } 
}

关于上边代码中的全局和局部变量,这里稍微说一下 SASS 的缺点,同名局部变量会覆盖全局变量的值,这很不自然

//SASS这一点不如LESS
$color: black;           
.scoped { 
    $color: white;
    color: $color;        
}                        
.unscoped {     
    // LESS = black (global)
    // SASS = white (overwritten by local)
    color: $color;          
}

有了变量,自然可以进行对值的计算

//Calculating in SASS
//以下代码中修改页面宽度只需要改一次
$width: 500px;
$sidebar_percent: 0.2;
#page {
    width: $width;
    #sidebar {width: $width * $sidebar_percent;}
    #content {width: $width * (1 - $sidebar_percent);} 
}

变量还可以嵌入字符串中,这在编程语言中称为插值(Interpolating)

//CSS 
.car.bmw_make {color: blue;}   
.car.bmw_make .image {
    background: url("images/bmw.png");
}
//Interpolating in SASS
$car: "bmw";

.car.#{$car}_make {s
    color: blue;
    .image {
        background: url("images/#{$car}.png");
    }
}

函数 (function)

在编程语言中,函数是仅此于变量的基本结构体,SASS 中有很多预定义函数,这里用颜色相关的函数举例如下

/*CSS需要定义整套颜色*/
.main {color: #336699;}
.lighten {color: #6699cc;}
.saturate {color: #1466b8;}    
//SASS只需要定义一个基本颜色,其他可以通过函数获取
$main_color: #336699;
.main {color: $main_color;}
.lighten {color: lighten($main_color, 20%);}    
.saturate {color: saturate($main_color, 30%);}    

SASS 的底层函数相当完整,如果会使用 ruby 的话,也可以自定义函数,完整列表在这里


导入 (import)

在样式表过于复杂的时候,你可以将其按功能模块分割成不同的文件进行开发,SASS 会将这些小文件统一编译成一个完整的 CSS 文件,与简单的包含多个文件不同,SASS 的导入,是可以将变量,Mixin,等等一起导入的

//_colors.scss(被导入的SASS文件,通常用_开头,它们在编译过程中不会生成CSS文件)
$main_color: #336699;
//application.scss 导入文件
//SASS会自动加上_去寻找文件
@import "colors";
#page {color: $main_color;}

扩展 (extend)

@extend可以复制其他 class 或 id 的指定样式,让你无须再将逻辑上不相关的 class 放在一起,当然更不用复制粘贴了

//CSS
.blue_button, .checkout_button {background: #336699;}
.blue_button {color: white;}
.checkout_button {color: green;}
//SASS @extend
.blue_button {
    background: #336699;
    color: white;
}

.checkout_button {
    @extend .blue_button;
    color: green;
}

混入 (mixin)

Mixin 可以说是 SASS 等 CSS 预处理语言最强大的要素了,简单来说,mixin 可以将一部分样式抽出,作为单独定义的模块,被很多选择器重复使用。

Mixin 可以定义在单独文件中

//_text.scss
@mixin blue_text {
    color: #336699;
    font-family: helvetica, arial, sans-serif;
    font-size: 20px;
    font-variant: small-caps; 
}   

导入并使用 mixin

@import "text";

.product_title {
    @include blue_text;
}

mixin 与 extend 看似实现的功能差不多,但实际上除了语义上的不同外,mixin 更为强大和复杂,因为她有参数 (arguments),参数还可以有默认值

实现跨浏览器圆角

//Cross browser Rounded borders mixin 
@mixin rounded_borders($color, $width: 5px, $rounding: 5px) {
    -moz-border-radius: $rounding $rounding;
    -webkit-border-radius: $rounding $rounding;
    -khtml-border-radius: $rounding $rounding;
    -o-border-radius: $rounding $rounding;
    border-radius: $rounding $rounding;
    border: $width $color solid; 
}

.header {
    @include rounded_borders(#336699, 3px);
}

实现跨浏览器透明度

//Cross browser Opacity mixin
@mixin opacity($opacity) {
    filter: alpha(opacity=#{$opacity*100}); // IE 5-9+
    opacity: $opacity; 
}

.h1 {
    @include opacity(0.6);
}

迭代 (each)

在主流语言中,迭代属于循环实现的一种功能,例如 ruby 的 each 或者 python 的 for in,sass 使用@each实现

/*CSS中要写很多同样的代码*/
.thom_picture {background-image: url("/image/thom.jpg");}
.jonny_picture {background-image: url("/image/jonny.jpg");}
.colin_picture {background-image: url("/image/colin.jpg");}
.phil_picture {background-image: url("/image/phil.jpg");}
//SASS使用@each变得非常简单
@each $member in thom, jonny, colin, phil {
    .#{$member}_picture {
        background-image: url("/image/#{$member}.jpg"); 
    } 
}

条件 (condition)

说到编程基本控制流,除了循环就是条件了,sass 中使用@if进行条件控制

//判断式中可以使用==/>/<等通常判别符
@mixin country_color($country) {
    @if $country == france {
        color: blue; 
    }
    @else {
        color: red; 
    } 
}

.england {
    @include country_color(england);
}
.france {
    @include country_color(france);
}


Compass

以上 SASS 的基本要素都介绍的差不多了,不过对于在实践中使用 SASS 来说,强大的Compass是必不可少的,她由 SASS 的核心团队成员 Chris Eppstein 创建,是一个非常丰富的样式框架,包括大量定义好的 mixin,函数,以及对 SASS 的扩展。

这里非常简要地介绍一些常用功能

Reset

Compass 提供一个基于大名鼎鼎的 Eric Meyer 的 Reset CSS,我还没有和 Twitter Bootstrap 采用的 Normalize.css 一一比对过,不过 compass reset 的好处是可以分不同的模块 reset

//compass reset
//global reset
@import "compass/reset";

//partial reset 
@import "compass/reset/utilities";

CSS3

前边提到的圆角和透明 mixin 实际上都在 Compass 中提供,当然还有几乎所有的 css3 相关模块,实际上有了 Compass,不需要再写任何浏览器特定的代码了。

//compass rounder corners
@import "compass/css3/border-radius";

.header {
    @include border-radius(4px); 
}

.header_top_left_rounded {
    @include border-top-left-radius(4px);
}

Typography

Compass 有很多基本 mixin 可以方便地定制各种表现层元素

比如水平列表,这个在顶部导航栏中相当常用

//Compass
@import "compass/typography/lists/horizontal-list";

ul.horiz {
    @include horizontal-list(4px); 
}

我们看一眼在 css 中的对应实现多么复杂

/*CSS实现*/
ul.horiz {
    margin: 0;
    padding: 0;
    border: 0;
    overflow: hidden;
    *zoom: 1; 
}
ul.horiz li {
    list-style-image: none;
    list-style-type: none;
    margin-left: 0px;
    white-space: nowrap;
    display: inline;
    float: left;
    padding-left: 4px;
    padding-right: 4px; 
}
ul.horiz li:first-child, ul.horiz li.first {
    padding-left: 0; 
}
ul.horiz li:last-child {
    padding-right: 0; 
}
ul.horiz li.last {
    padding-right: 0; 
}

Layout

Compass 也提供一些影响布局的方法,比如将一个元素延展 (Stretch)

HTML 如下

<div class="stretch_box">
    <div class="stretched>
        Stretched fully!
    </div>
</div>
//compass stretching
@import "compass/layout/stretching";

//stretched fully
.stretched {
    @include stretch; 
}

//stretched with gap
.stretched {
    @include stretch(12px, 12px, 12px, 12px); 
}

//stretched horizontally
.stretched {
    @include stretch-x; 
}

Utilities

Compass 还有很多实用功能模块,比如很烦人但在布局中经常要使用的 clearfix,有了这个 mixin,就不需要再定义一个 clearfix 的 class,然后污染 outer_box 的 html 了

//Compass clearfix
    @import "compass/utilities/general/clearfix";

    #outer_box {
        @include clearfix;
        width: 500px;
        #inner_box {
            float: left;
            width: 200px;
            height: 100px;
        }
    }

另外一个强大的功能是 css sprites,原来我们经常用 photoshop 手动生成这张集合了所有小图标的大图片,修改和维护如同噩梦,现在有了 compass,一切轻松了。

//compass sprites
//combines all images in icon folder into one
@import "icon/*.png";

//"movie" is the origin icon's file name
.movie_icon {
    height: 20px;
    @include icon-sprite(movie); 
}

整篇介绍到这里就结束了,其实,无论是 SASS 这样的 CSS 预处理器,还是 Compass 这样的框架,要达成的目的都是一致的,那就是遵循DRY, 可读性, 和正交化的设计原则,让我们的生活变得更轻松快乐。


感谢分享。

干货!

给力, 希望能有更多的介绍

嘿,来贴个完美背景透明(文字不透明):

@mixin better_transparentize($color, $alpha)
  $c: rgba($color, $alpha)
  $ie_c: ie_hex_str($c)
  background: rgba($color, 1)
  background: $c
  background: transparent\9
  zoom: 1
  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#{$ie_c}, endColorstr=#{$ie_c})
  -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#{$ie_c}, endColorstr=#{$ie_c})"

使用:

.box
  @include better_transparentize(white, .8)

http://fancyoung.com/blog/better-transparentize-mixin-for-sass/

#4 楼 @siyang1982 赞,这个应该直接提给 compass,他们只支持跨浏览器 opacity,貌似没有跨浏览器 alpha 通道

SASS 的变量特性我没测试过。不过要是按照你所说的那样的话,SASS 就压根没有局部变量这一说了,括号根本没起到限定作用域的用处。也就是说都是全局变量。还真是不太好的样子。

学习了:)

待会看,谢谢!
我在想,如果也把{}去掉,通过缩进来写,是不是更好看一些?

学习了:)

很详细 很全面

楼主 我感觉最大的问题是如何支持 ie6 特别是 grid 能否给点建议呢 谢谢

@lilu 我打算开始用 cmpass,但是看了你的帖子,感觉 compass 和 bootstrap 还是有些重叠,比如 bootstrap 也有 reset, mixins.scss 中也定义 clearfix 等,那如何组合使用他们两者?是不是又了 bootstrap,compass 有些多余?

感谢分享。 我一直以为 sass 是 scss 之后的版本。 原来弄错了。 sass 的缩进,如果多屏的行数也是一个头疼的问题, 不过 scss 那个太多的括号也经常搞晕,不过加入一些注释会好一些。

上班前无意翻到的,Mark 下,回去接着看

不错,学习是一个一步下往深处走的过程《最详细的 Sass 基础教程指南http://yunkus.com/article/css3/290.html

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册