使用compass自动合并css雪碧图

         css雪碧图又叫css精灵css sprite,是一种背景图片的拼合技术。使用css雪碧图,能够减少页面的请求数、降低图片占用的字节,以此来达到提升页面访问速度的目的。但是它也有令人诟病的地方,就是拼图和后期维护的成本比较大。也正是因为这一点,导致很多开发者懒于使用css雪碧图。

对于这种耗时、枯燥、重复性的工作,最好的解决方法还是交给工具去处理。本文就介绍下怎样使用compass来自动合并css雪碧图。

compass

安装compass

首先请确认电脑已经安装rubysass环境,rubysass的安装过程可参考:

sass入门指南

安装完成后可通过以下指令确认:

$ ruby -v
ruby 2.0.0p451 (2014-02-24) [x64-mingw32]
$ sass -v
Sass 3.4.6 (Selective Steve)

接着安装compass:

$ gem install compass

// 查看compass版本
$ compass -v
Compass 1.0.1 (Polaris)

ps: 本文中代码运行环境为:sass: 3.4.6, compass: 1.0.1, 测试时请确认sass版本不低于3.4.6,compass版本不低于1.0.1

配置compass项目

进入项目目录,命令行中运行:

$ compass init

会生成相应的目录和配置文件。在images目录下建立share目录存放需合并的图标。项目目录结构如下:

- sass
- stylesheet
- images
  |-- share
  |-- magic
  |-- setting

config.rb文件配置如下:

http_path = "/"
css_dir = "stylesheets"
sass_dir = "sass"
images_dir = "images"
javascripts_dir = "javascripts"

relative_assets = true    // 使用相对目录
line_comments = false    // 关闭行注释

完整的项目目录示例可在github上查看:https://github.com/Bubblings/compass-sprite

合并雪碧图

输出所有雪碧图样式

sass目录下新建share.scss文件,并写入以下代码:

@import "compass/utilities/sprites";    // 加载compass sprites模块
@import "share/*.png";                    // 导入share目录下所有png图片
@include all-share-sprites;                // 输出所有的雪碧图css

命令行调用compass compile进行编译,此时会发现images目录下出现了一个合并后的图片share-xxxxxxxx.png, stylesheet目录下生成了对应的share.css文件:

.share-sprite, .share-github, .share-qq, .share-weibo {
  background-image: url('../images/share-s7fefca4b98.png');
  background-repeat: no-repeat;
}

.share-github {
  background-position: 0 0;
}

.share-qq {
  background-position: 0 -23px;
}

.share-weibo {
  background-position: 0 -47px;
}

至此,我们就实现了一个简单的雪碧图合并,而且只用了三行代码。是不是有点小激动^_^。 生成的代码中.share-sprite是雪碧图的基础类,后面介绍配置时会详细说明。生成的每个雪碧图默认的class规则是:.目录名-图片名。如果想自定义,我们可以通过下面调用单个雪碧图的方式来实现。

调用单个雪碧图样式

sass目录下新建single-share.scss文件,并写入以下代码:

@import "compass/utilities/sprites";    // 加载compass sprites模块
@import "share/*.png";                    // 导入share目录下所有png图片
.test {
    @include share-sprites(github);
}

编译后的css为:

.share-sprite, .test {
  background-image: url('../images/share-s7fefca4b98.png');
  background-repeat: no-repeat;
}

.test {
  background-position: 0 -23px;
}

利用魔术精灵选择器智能输出

有的时候我们的图标会有多种状态,比如hover, active, focus, target等。利用compass的魔术精灵选择器我们就可以智能的合并各状态的图标,并输出对应的css。使用时,我们需要将图标按照一定的规则命名。例如:

weibo.png            // 默认状态图标
weibo_hover.png     // hover状态图标
weibo_active.png     // active状态图标

sass目录下新建magic.scss文件,并写入以下代码:

@import "compass/utilities/sprites";
@import "magic/*.png";
@include all-magic-sprites;

编译后的css为:

.magic-sprite, .magic-weibo {
  background-image: url('../images/magic-s758f6928e8.png');
  background-repeat: no-repeat;
}

.magic-weibo {
  background-position: 0 0;
}
.magic-weibo:hover, .magic-weibo.weibo-hover {
  background-position: 0 -48px;
}
.magic-weibo:active, .magic-weibo.weibo-active {
  background-position: 0 -24px;
}

雪碧图配置

我们已经利用compass实现了简单雪碧图的合成。当然compass还提供了很多可供配置的选项,下面来一一介绍。

PS: 以下的配置选项不再单独举例,可参考示例项目中的setting.scss文件。

先来看下配置相关的语法:

$<map>-<property>: setting;                // 配置所有sprite
$<map>-<sprite>-<property>: setting;    // 配置单个sprite

说明:

  • <map>: 对应图标存放的文件夹名称,如上面例子中的:sharemagic
  • <sprite>: 对应单个图标的名称,如上面例子中的: weibo, qq, github

配置sprite间距

$<map>-spacing: 5px;                // 配置所有sprite间距为5px,默认为0px
$<map>-<sprite>-spacing: 10px;        // 配置单个sprite间距为10px,默认继承$<map>-spacing的值

配置sprite重复性

$<map>-repeat: no-repeat/repeat-x;        // 配置所有sprite的重复性,默认为no-repeat
$<map>-<sprite>-repeat: no-repeat/repeat-x;// 配置单个sprite的重复性,默认继承$<map>-repeat的值

配置sprite的位置

$<map>-position: 0px;                // 配置所有sprite的位置,默认为0px
$<map>-<sprite>-position: 0px;        // 配置单个sprite的位置,默认继承$<map>-position的值

配置sprite的布局方式

$<map>-layout: vertical/horizontal/diagonal/smart;        // 默认布局方式为vertical

清除过期的sprite

$<map>-clean-up: true/false;        // 默认值为true

每当添加、删除或改变图片后,都会生成新的sprite,默认情况下compass会自动的移除旧的sprite,当然也可以通过配置$<map>-clean-up: false;来保留旧的sprite。

配置sprite的基础类

在使用sprite时,compass会自动的生成一个基础类来应用公用的样式(如background-image),默认的类名为$<map>-sprite,上面例子中的.share-sprite, .magic-sprite就是这个基础类,当然compass也提供了自定义这个类名的选项:

$<map>-sprite-base-class: ".class-name";

魔术精灵选择器开关

上面已经介绍了怎样利用利用魔术精灵选择器智能输出sprite,默认情况下compass是开启这个功能的,也就是说compass默认会将以_hover, _active等名字结尾的图片自动输出对应的:hover, :active等伪类样式。当然如果不想这样的话,也可以禁用它。

$disabled-magic-sprite-selectors: false;    // 默认为true

设置sprite尺寸

我们在合并雪碧图时,很多时候图片的尺寸都不一样,那么在使用时我们如何给每个sprite设置尺寸呢?compass有提供自动设置每个sprite尺寸的配置,默认是关闭的,我们只需手动启用即可。

$setting-sprite-dimensions: true;    // 启用自动设置sprite尺寸,默认值为false

这时输出的样式中会自动加上图片的尺寸,例如:

.setting-compass {
  background-position: -5px 0;
  height: 35px;
  width: 200px;
}

当然,如果只对某个sprite单独设置的话,compass也提供了这个功能。语法如下:

$<map>-sprite-width($name);     // $name为合并前的图片名称
$<map>-sprite-height($name);

例如:

.special {
    @include setting-sprite(compass);
    width: setting-sprite-width(compass);
    height: setting-sprite-height(compass);
}

则输出的css为:

.special {
  background-position: -5px 0;
  width: 200px;
  height: 35px;
} 

使用Compass生成雪碧图

         CSS雪碧图是将几个图片拼合成一张图片,以此来减少HTTP请求的方法,并且可以提升网站加载性能。除了使用传统方法在Photoshop中手动拼合,还有一些简便的方法和便捷的工具来帮助我们完成这项工作。

但是,以我处理CSS雪碧图的经验来说,没有哪种方法比使用CompassSprite函数更轻松容易的了。现在就让我们来看看他是如何工作的

开始使用Compass

在使用Compass工作之前,我们需要创建一个Compass的项目然后监视它。这样,当这个项目中包含的图片和.scss一发生改变,Compass就会编译成合适的形式。

让我们打开你的终端或者命令行窗口(如果你使用的是Windows),然后运行下面的这段命令。

compass create /path/to/project  
cd /path/to/project  
compass watch  

合并图片

正如我们上面提到的,你可以使用Photoshop来手动增减图片或者你也可以使用一些便捷的工具,例如:SpriteBox或者SpriteMe。Compass将这些功能整合成一个函数。我们在images/browsers/这个文件夹下有一些icon图片,命名为XXX.png。

使用Compass生成雪碧图

特别声明:以上icon由Futurosoft制作

在Compass中添加这些icon,我们可以在.scss文件中使用@import语法指向图片文件夹下的所有png扩展名的图片。就像下面这样:

@import "browsers/*.png";  

保存文件后,Compass将会将这些图片进行合并,然后生成一个新的图片文件,如下:

使用Compass生成雪碧图

雪碧图陈列方向(即合并完后的图片是横向排列还是纵向排列)

此外,我们还可以设置雪碧图排列的方向。正如你之前看到的图片截屏,图片默认排列是纵向的。假设纵向排列不能适应当前的情况下,我们可以使用$<map>-layout: horizontal;或者$<map>-layout: diagonal;变量来指定他们水平排列或者对角线排列,将变量中的<map>替换成你存储图片的文件夹的名字。

水平排列例子

$browsers-layout:horizontal;  
@import "browsers/*.png";

使用Compass生成雪碧图

对角线排列例子

$browsers-layout:vertical;  
@import "browsers/*.png";  

使用Compass生成雪碧图

在样式表中添加图片

一旦我们将图片合并完,我们就可以在样式表中的背景图中调用它了。我们用传统的做法就可以了。

.chrome {   
    background-position: 0 0; width: 128px; height: 128px;   
}   
.firefox {   
    background-position: 0 -133px; width: 128px; height: 128px;   
}   
.ie {   
    background-position: 0 -266px; width: 128px; height: 128px;   
}   
.opera {   
    background-position: 0 -399px; width: 128px; height: 128px;   
}   
.safari {   
    background-position: 0 -532px; width: 128px; height: 128px;   
}   

在Compass中,我们有更简单的的方法。首先,我们用@include all-<map>-sprites这个语法来生成一些CSS规则,其中,将<map>替换成我们存放图片的文件夹名称。

@include  all-browsers-sprites; 

当上面这行编译成正常的CSS时,除了会生成背景图的声明,还有对应的位置,正如下面展示的。

.browsers-sprite, .browsers-chrome, .browsers-firefox, .browsers-ie, .browsers-opera, .browsers-safari {  
  background: url('/images/browsers-sad8e949931.png') no-repeat;  
}  
.browsers-chrome {  
    background-position: 0 0;  
}  
.browsers-firefox {  
    background-position: 0 -128px;  
}  
.browsers-ie {  
    background-position: 0 -256px;  
}  
.browsers-opera {  
    background-position: 0 -384px;  
}  
.browsers-safari {  
    background-position: 0 -512px;  
}  

或者,我们也可以用@include <map>-sprite(image-naem)语法将背景图中的某一个对应的位置图片传给指定的选择器:和前面的代码一样,只需要将<map>替换成存储图片的文件夹名字即可。下面是一个例子。

li {  
    @include browsers-sprite(safari);  
} 

然后,Compass会聪明的识别出背景的位置,不用我们明确指定。在正常的CSS中,上面那行代码会转换成:

.browsers-sprite, li {  
  background: url('/images/browsers-sad8e949931.png') no-repeat;  
}  
li {  
    background-position: 0 -512px;  
}  

指定容器的尺寸

最后我们需要做的就是指定需要显示背景图容器的宽高属性。我们传统的做法是手动查看图片的宽和高(绝大多数情况是通过查看图片信息或图片属性获得)。

使用Compass,我们就可以使用 <map>-sprite-height(image-name)或者<map>-sprite-width(image-name)函数来获取到图片的宽和高。在下面这个例子中,我们会获取其中一个图片的宽和高,并将值存储给变量。再使用@include指令获得分配背景图。

$height: browsers-sprite-height(safari);  
$width: browsers-sprite-width(safari);  
li {  
    display: inline-block;  
    height: $height;  
    width: $width;  
    @include browsers-sprite(safari);  
}  

当我们编译上面这些代码,他就会转成下面这些正常的CSS。

.browsers-sprite, li {  
    background: url('/images/browsers-sad8e949931.png') no-repeat;  
}  
li {  
    display: inline-block;  
    height: 128px;  
    width: 128px;  
    background-position: 0 -512px;  
} 

结论

实际上,Compass除了这些创建CSS雪碧图的基本函数,Compass还有很多有用的函数可以使用。然而,如果你是Compass的新手,我们建议你关注我们之前写的关于Sass和Compass的文章。我们希望这些文章对你有所帮助。

译者手语:整个翻译依照原文线路进行,并在翻译过程略加了个人对技术的理解。如果翻译有不对之处,还烦请同行朋友指点。谢谢!

文章出处:

英文出处:http://www.hongkiat.com/blog/compass-image-sprite/

中文译文:http://www.w3cplus.com/preprocessor/compass-image-sprite.html

Sass基础——Sass函数

     在Sass中除了可以定义变量,具有@extend,%placeholders和Mixins等特性之外,还自备了一系列的函数功能。前面在《Sass基础——颜色函数》一文中主要向大家介绍了Sass函数中有关于颜色函数的功能以及使用。其实在Sass的函数功能中除了颜色函数之外,还具有字符串函数数字函数列表函数Introspection函数以及三元函数等,当然大家还可以根据需求自定义函数

在这篇文章中,我们主要对Sass函数中的字符串函数数字函数列表函数Introspection函数以及三元函数的功能能使用做一些简单的介绍,希望对初学Sass的同学略有帮助。

字符串函数

字符串函数顾名思意是用来处理字符串的函数。Sass的字符串函数主要包括两个函数:

unquote()函数

unquote()函数主要是用来删除一个字符串中的引号,如果这个字符串没有带有引号,将返回原始的字符串。简单的使用终端来测试这个函数的运行结果:

//SCSS
.test1 {
    content:  unquote('Hello Sass!') ;
}
.test2 {
    content: unquote("'Hello Sass!");
}
.test3 {
    content: unquote("I'm Web Designer");
}
.test4 {
    content: unquote("'Hello Sass!'");
}
.test5 {
    content: unquote('"Hello Sass!"');
}
.test6 {
    content: unquote(Hello Sass);
}

//CSS
.test1 {
  content: Hello Sass!; }

.test2 {
  content: 'Hello Sass!; }

.test3 {
  content: I'm Web Designer; }

.test4 {
  content: 'Hello Sass!'; }

.test5 {
  content: "Hello Sass!"; }

.test6 {
  content: Hello Sass; }

从测试的效果中可以看出,unquote()函数只能删除字符串最前和最后的引号(双引号或单引号),而无法删除字符串中间的引号。如果字符没有带引号,返回的将是字符串本身。

quote()函数

quote()函数刚好与unquote()函数功能相反,主要用来给字符串添加引号。如果字符串,自身带有引号会统一换成双引号""。如:

//SCSS
.test1 {
    content:  quote('Hello Sass!');
}
.test2 {
    content: quote("Hello Sass!");
}
.test3 {
    content: quote(ImWebDesigner);
}
.test4 {
    content: quote(' ');
}
//CSS
.test1 {
  content: "Hello Sass!"; 
}

.test2 {
  content: "Hello Sass!"; 
}

.test3 {
  content: "ImWebDesigner"; 
}
.test4 {
  content: " "; 
}

使用quote()函数增加只能给字符串增加双引号,而且字符串中间有单引号或者空格时,需要用单引号或双引号括起,否则编译的时候将会报错。

.test1 {
    content:  quote(Hello Sass);
}

这样使用,编译器马上会报错:

error style.scss (Line 13: $string: ("Hello" "Sass") is not a string for `quote')

解决方案就是去掉空格,或者加上引号:

.test1 {
    content:  quote(HelloSass);
}
.test1 {
    content:  quote("Hello Sass");
}

同时quote()碰到特殊符号,比如说!?>等,除中折号-和下划线_都需要使用双引号括起,否则编译器在进行编译的时候同样会报错:

error style.scss (Line 13: Invalid CSS after "...quote(HelloSass": expected ")", was "!);")
error style.scss (Line 16: Invalid CSS after "...t:  quote(Hello": expected ")", was "?);")

数字函数

Sass中的数字函数提要针对数字方面提供一系列的函数功能:

看到上面函数的简介,对于熟悉javascript同学而言并不会感觉陌生。因为他们有很多功能都非常类似,接下来对每个函数进行一些简单的测试。

percentage()

percentage()函数主要是将一个不带单位的数字转换成百分比形式:

>> percentage(.2)
20%
>> percentage(2px / 10px)
20%
>> percentage(2em / 10em)
20%
>>

如果您转换的值是一个带有单位的值,那么在编译的时候会报错误信息:

>> percentage(2px / 10em)
SyntaxError: $value: 0.2px/em is not a unitless number for `percentage'

round()函数

round()函数将一个数四舍五入为一个最接近的整数:

>> round(12.3)
12
>> round(12.5)
13
>> round(1.49999)
1
>> round(2.0)
2
>> round(20%)
20%
>> round(2.2%)
2%
>> round(3.9em)
4em
>> round(2.3px)
2px
>> round(2px / 3px)
1
>> round(1px / 3px)
0
>> round(3px / 2em)
2px/em

round()函数中可以携带单位的任何数值。

ceil()函数

ceil()函数将一个数转换成最接近于自己的整数,会将一个大于自身的任何小数转换成大于本身1的整数。也就是只做入,不做舍的计算:

>> ceil(2.0)
2
>> ceil(2.1)
3
>> ceil(2.6)
3
>> ceil(2.3%)
3%
>> ceil(2.3px)
3px
>> ceil(2.5px)
3px
>> ceil(2px / 3px)
1
>> ceil(2% / 3px)
1%/px
>> ceil(1em / 5px)
1em/px

floor()函数

floor()函数刚好与ceil()函数功能相反,其主要将一个数去除其小数部分,并且不做任何的进位。也就是只做舍,不做入的计算:

>> floor(2.1)
2
>> floor(2.5)
2
>> floor(3.5%)
3%
>> floor(10.2px)
10px
>> floor(10.8em)
10em
>> floor(2px / 10px)
0
>> floor(3px / 1em)
3px/em

abs()函数

abs()函数会返回一个数的绝对值。

>> abs(10)
10
>> abs(-10)
10
>> abs(-10px)
10px
>> abs(-2em)
2em
>> abs(-.5%)
0.5%
>> abs(-1px / 2px)
0.5

min()函数

min()函数功能主要是在多个数之中找到最小的一个,这个函数可以设置任意多个参数:

>> min(1,2,1%,3,300%)
1%
>> min(1px,2,3px)
1px
>> min(1em,2em,6em)
1em

不过在min()函数中同时出现两种不同类型的单位,将会报错误信息:

>> min(1px,1em)
SyntaxError: Incompatible units: 'em' and 'px'.

max()函数

max()函数和min()函数一样,不同的是,max()函数用来获取一系列数中的最大那个值:

>> max(1,5)
5
>> max(1px,5px)
5px

同样的,如果在max()函数中有不同单位,将会报错:

>> max(1,3px,5%,6)
SyntaxError: Incompatible units: '%' and 'px'.

List函数

列表函数主要包括一些对列表参数的函数使用,主要包括以下几种:

列表函数中的每个函数都有其独特的作用与功能,接下来我们通过命令终端向大家展示每个列表函数的功能与使用。

length()函数

length()函数主要用来返回一个列表中有几个值,简单点说就是返回列表清单中有多少个值:

>> length(10px)
1
>> length(10px 20px (border 1px solid) 2em)
4
>> length(border 1px solid)
3

length()函数中的列表参数之间使用空格隔开,不能使用逗号,否则函数将会把错:

>> length(10px,20px,(border 1px solid),2em)
SyntaxError: wrong number of arguments (4 for 1) for `length'
>> length(1,2px)
SyntaxError: wrong number of arguments (2 for 1) for `length'

nth()函数

nth()函数用来指定列表中某个位置的值。不过在Sass中,nth()函数和其他语言不同,1是指列表中的第一个标签值,2是指列给中的第二个标签值,依此类推。如:

>> nth(10px 20px 30px,1)
10px
>> nth((Helvetica,Arial,sans-serif),2)
"Arial"
>> nth((1px solid red) border-top green,1)
(1px "solid" #ff0000)

注:nth($list,$n)函数中的$n必须是大于0的整数:

>> nth((1px solid red) border-top green 1 ,0)
SyntaxError: List index 0 must be a non-zero integer for `nth'

join()函数

join()函数是将两个列表连接合并成一个列表。

>> join(10px 20px, 30px 40px)
(10px 20px 30px 40px)
>> join((blue,red),(#abc,#def))
(#0000ff, #ff0000, #aabbcc, #ddeeff)
>> join((blue,red),(#abc #def))
(#0000ff, #ff0000, #aabbcc, #ddeeff)

不过join()只能将两个列表连接成一个列表,如果直接连接两个以上的列表将会报错:

>> join((blue red),(#abc, #def),(#dee #eff))
SyntaxError: $separator: (#ddeeee #eeffff) is not a string for `join'

但很多时候不只碰到两个列表连接成一个列表,这个时候就需要将多个join()函数合并在一起使用:

>> join((blue red), join((#abc #def),(#dee #eff)))
(#0000ff #ff0000 #aabbcc #ddeeff #ddeeee #eeffff)

join()函数中还有一个很有特别的参数$separator,这个参数主要是用来给列表函数连接列表值是,使用的分隔符号,默认值为auto

join()函数中$separator除了默认值auto之外,还有commaspace两个值,其中comma值指定列表中的列表项值之间使用逗号,)分隔,space值指定列表中的列表项值之间使用空格( )分隔。

join()函数中除非明确指定了$separator值,否则将会有多种情形发生:

如果列表中的第一个列表中每个值之间使用的是逗号(,),那么join()函数合并的列表中每个列表项之间使用逗号,分隔:

>> join((blue, red, #eff),(green orange))
(#0000ff, #ff0000, #eeffff, #008000, #ffa500)

但当第一个列表中只有一个列表项,那么join()函数合并的列表项目中每个列表项目这间使用的分隔符号会根据第二个列表项中使用的,如果第二列表项中使用是,分隔,则使用逗号分隔;如果第二列项之间使用的空格符,则使用空格分隔:

>> join(blue,(green, orange))
(#0000ff, #008000, #ffa500)
>> join(blue,(green orange))
(#0000ff #008000 #ffa500)

如果列表中的第一个列表中每个值之间使用的是空格,那么join()函数合并的列表中每个列表项之间使用空格分隔:

>> join((blue green),(red,orange))
(#0000ff #008000 #ff0000 #ffa500)
>> join((blue green),(red orange))
(#0000ff #008000 #ff0000 #ffa500)

如果当两个列表中的列表项小于1时,将会以空格分隔:

>> join(blue,red)
(#0000ff #ff0000)

如此一来,会有多种情形发生,造成使用混乱的情形,如果你无法记得,什么时候会是用逗号分隔合并的列表项,什么时候是使用空格分隔合并的列表项,在些建议大家使用join()函数合并列表项的时候就明确指定$separator参数,用来指定合并的列表中使用什么方式来分隔列表项:

>> join(blue,red,comma)
(#0000ff, #ff0000)
>> join(blue,red,space)
(#0000ff #ff0000)
>> join((blue green),(red,orange),comma)
(#0000ff, #008000, #ff0000, #ffa500)
>> join((blue green),(red,orange),space)
(#0000ff #008000 #ff0000 #ffa500)
>> join((blue, green),(red,orange),comma)
(#0000ff, #008000, #ff0000, #ffa500)
>> join((blue, green),(red,orange),space)
(#0000ff #008000 #ff0000 #ffa500)
>> join(blue,(red,orange),comma)
(#0000ff, #ff0000, #ffa500)
>> join(blue,(red,orange),space)
(#0000ff #ff0000 #ffa500)
>> join(blue,(red orange),comma)
(#0000ff, #ff0000, #ffa500)
>> join(blue,(red orange),space)
(#0000ff #ff0000 #ffa500)

append()函数

append()函数是用来将某个值插入到列表中,并且处于最末位。

>> append(10px 20px ,30px)
(10px 20px 30px)
>> append((10px,20px),30px)
(10px, 20px, 30px)
>> append(green,red)
(#008000 #ff0000)
>> append(red,(green,blue))
(#ff0000 (#008000, #0000ff))

如果没有明确的指定$separator参数值,其默认值是auto。如果列表只有一个列表项时,那么插入进来的值将和原来的值会以空格的方式分隔。如果列表中列表项是以空格分隔列表项,那么插入进来的列表项也将以空格分隔;如果列表中列表项是以逗号分隔列表项,那么插入进来的列表项也将以逗号分隔。

当然,在append()函数中,可以显示的设置$separator参数,如果取值为comma将会以逗号分隔列表项,如果取值为space将会以空格分隔列表项:

>> append((blue green),red,comma)
(#0000ff, #008000, #ff0000)
>> append((blue green),red,space)
(#0000ff #008000 #ff0000)
>> append((blue, green),red,comma)
(#0000ff, #008000, #ff0000)
>> append((blue, green),red,space)
(#0000ff #008000 #ff0000)
>> append(blue,red,comma)
(#0000ff, #ff0000)
>> append(blue,red,space)
(#0000ff #ff0000)

zip()函数

zip()函数将多个列表值转成一个多维的列表:

>> zip(1px 2px 3px,solid dashed dotted,green blue red)
((1px "solid" #008000), (2px "dashed" #0000ff), (3px "dotted" #ff0000))

在使用zip()函数时,每个单一的列表个数值必须是相同的:

>> zip(1px 2px 3px, solid , green blue red)
NoMethodError: undefined method `options=' for nil:NilClass
  Use --trace for backtrace.

否则将会出错。

zip()函数中每个单一列表的值对应的取其相同位置值:

|--- List ---|--- nth(1) ---|--- nth(2) ---|--- nth(3) ---|
|------------|--------------|--------------|--------------|
|    List1   |      1px     |      2px     |      3px     |
|------------|--------------|--------------|--------------|
|    List2   |      solid   |      dashed  |     dotted   |
|------------|--------------|--------------|--------------|
|    List3   |      green   |      blue    |      red     |
|------------|--------------|--------------|--------------|

zip()函数组合出来就成了:

1px solid green, 2px dashed blue, 3px dotted red

index()函数

index()函数类似于索引一样,主要让你找到某个值在列表中所处的位置。在Sass中,第一个值就是1,第二个值就是2,依此类推:

>> index(1px solid red, 1px)
1
>> index(1px solid red, solid)
2
>> index(1px solid red, red)
3

index()函数中,如果指定的值不在列表中(没有找到相应的值),那么返回的值将是false,相反就会返回对应的值在列表中所处的位置。

>> index(1px solid red,dotted) //列表中没有找到dotted
false
>> index(1px solid red,solid) //列表中找到solid值,并且返回他的位置值2
2

Introspection函数

Introspection函数包括了几个判断型函数:

这几个函数主要用来对值做一个判断的作用,依次来看每个函数的功能。

type-of()函数

type-of()函数主要用来判断一个值是属于什么类型:

>> type-of(100)
"number"
>> type-of(100px)
"number"
>> type-of("asdf")
"string"
>> type-of(asdf)
"string"
>> type-of(true)
"bool"
>> type-of(false)
"bool"
>> type-of(#fff)
"color"
>> type-of(blue)
"color"
>> type-of(1 / 2 = 1)
"string"

unit()函数

unit()函数主要是用来获取一个值所使用的单位,碰到复杂的计算时,其能根据运算得到一个多单位组合的值,不过只充许乘除运算:

>> unit(100)
""
>> unit(100px)
"px"
>> unit(20%)
"%"
>> unit(1em)
"em"
>> unit(10px * 3em)
"em*px"
>> unit(10px / 3em)
"px/em"
>> unit(10px * 2em / 3cm / 1rem)
"em/rem"

但加减碰到不同单位时,unit()函数将会报错,除pxcmmm运算之外:

>> unit(1px + 1cm)
"px"
>> unit(1px - 1cm)
"px"
>> unit(1px + 1mm)
"px"
>> unit(10px * 2em - 3cm / 1rem)
SyntaxError: Incompatible units: 'cm' and 'px*em'.
>> unit(10px * 2em - 1px / 1rem)
SyntaxError: Incompatible units: '' and 'em'.
>> unit(1px - 1em)
SyntaxError: Incompatible units: 'em' and 'px'.
>> unit(1px - 1rem)
SyntaxError: Incompatible units: 'rem' and 'px'.
>> unit(1px - 1%)
SyntaxError: Incompatible units: '%' and 'px'.
>> unit(1cm + 1em)
SyntaxError: Incompatible units: 'em' and 'cm'.

unit()函数对于单位运算相对来说也没有规律,而且有些单位也无法整合成一个单位,对于我们在CSS中运用中并不适合,比如:

>> unit(10px * 3em)
"em*px"
>> unit(10px / 3em)
"px/em"
>> unit(10px * 2em / 3cm / 1rem)
"em/rem"

换句话说,上面运算出来的单位,对于在CSS中使用将是没有任何意义的。

unitless()函数

unitless()函数相对来说简单明了些,只是用来判断一个值是否带有单位,如果不带单位返回的值为true,带单位返回的值为false

>> unitless(100)
true
>> unitless(100px)
false
>> unitless(100em)
false
>> unitless(100%)
false
>> unitless(1 /2 )
true
>> unitless(1 /2 + 2 )
true
>> unitless(1px /2 + 2 )
false

comparable()函数

comparable()函数主要是用来判断两个数是否可以进行加,减以及合并。如果可以返回的值为true,如果不可以返回的值是false

>> comparable(2px,1px)
true
>> comparable(2px,1%)
false
>> comparable(2px,1em)
false
>> comparable(2rem,1em)
false
>> comparable(2px,1cm)
true
>> comparable(2px,1mm)
true
>> comparable(2px,1rem)
false
>> comparable(2cm,1mm)
true

Miscellaneous函数

在这里把Miscellaneous函数称为三元条件函数,主要因为他和JavaScript中的三元判断非常的相似。他有两个值,当条件成立返回一种值,当条件不成立时返回另一种值:

if($condition,$if-true,$if-false)

上面表达式的意思是当$condition条件成立时,返回的值为$if-true,否则返回的是$if-false值。

>> if(true,1px,2px)
1px
>> if(false,1px,2px)
2px

自定义函数

自定义函数是用户根据自己一些特殊的需求编写的Sass函数。在很多时候,Sass自带的函数并不能满足功能上的需求,所以很多时候需要自定义一些函数。

例如,我们需要去掉一个值的单位,在这种情形之下,Sass自带的函数是无法帮助我们完成,这个时候我们就需要定义函数:

//去掉一个值的单位,如12px => 12
// eg. strip-units(12px) => 12

@function strip-units($number){
    @return $number / ($number * 0 + 1);
}     

上在演示是一个经典的去除单位的自定义函数,除了这个函数之外,大家还可以根据自己需求定义其他的函数,正如前面介绍的pxToempxTorem两个自定义的函数。

总结

在这一节中,主要根据Sass的官网介绍的函数为范本,借助Sass的sass -i命令在终端向大家展示了Sass函数中的字符串函数数字函数列表函数Introspection函数以及三元函数等功能以及使用方法。并且在最后简单的介绍了在Sass中如何自定义Sass的函数。希望这篇文章对于初学者能更好的理解Sass中的自带函数的功能与作用。

转载:http://www.w3cplus.com/preprocessor/sass-other-function.html

sass语法

关于sass 3.3.0更新说明——3.3.0

sublime相关插件为:scss语法高亮sass语法高亮编译保存即编译格式化

文件后缀名

sass有两种后缀名文件:一种后缀名为sass,不使用大括号和分号;另一种就是我们这里使用的scss文件,这种和我们平时写的css文件格式差不多,使用大括号和分号。而本教程中所说的所有sass文件都指后缀名为scss的文件。在此也建议使用后缀名为scss的文件,以避免sass后缀名的严格格式要求报错。

//文件后缀名为sass的语法
body
  background: #eee
  font-size:12px
p
  background: #0982c1

//文件后缀名为scss的语法  
body {
  background: #eee;
  font-size:12px;
}
p{
  background: #0982c1;
} 

导入

sass的导入(@import)规则和CSS的有所不同,编译时会将@import的scss文件合并进来只生成一个CSS文件。但是如果你在sass文件中导入css文件如@import 'reset.css',那效果跟普通CSS导入样式文件一样,导入的css文件不会合并到编译后的文件中,而是以@import方式存在。

所有的sass导入文件都可以忽略后缀名.scss。一般来说基础的文件命名方法以_开头,如_mixin.scss。这种文件在导入的时候可以不写下划线,可写成@import "mixin"

被导入sass文件a.scss:

//a.scss
//-------------------------------
body {
  background: #eee;
}

需要导入样式的sass文件b.scss:

@import "reset.css";
@import "a";
p{
  background: #0982c1;
} 

转译出来的b.css样式:

@import "reset.css";
body {
  background: #eee;
}
p{
  background: #0982c1;
}

根据上面的代码可以看出,b.scss编译后,reset.css继续保持import的方式,而a.scss则被整合进来了。

注释

sass有两种注释方式,一种是标准的css注释方式/* */,另一种则是//双斜杆形式的单行注释,不过这种单行注释不会被转译出来。

标准的css注释

/*
*我是css的标准注释
*设置body内距
*/
body{
  padding:5px;
} 

双斜杆单行注释

单行注释跟JavaScript语言中的注释一样,使用又斜杠(//),但单行注释不会输入到CSS中。

//我是双斜杠表示的单行注释
//设置body内距
body{
  padding:5px; //5px
} 

变量

sass的变量必须是$开头,后面紧跟变量名,而变量值和变量名之间就需要使用冒号(:)分隔开(就像CSS属性设置一样),如果值后面加上!default则表示默认值。

普通变量

定义之后可以在全局范围内使用。

//sass style
//-------------------------------
$fontSize: 12px;
body{
    font-size:$fontSize;
}

//css style
//-------------------------------
body{
    font-size:12px;
}

默认变量

sass的默认变量仅需要在值后面加上!default即可。

//sass style
//-------------------------------
$baseLineHeight:        1.5 !default;
body{
    line-height: $baseLineHeight; 
}

//css style
//-------------------------------
body{
    line-height:1.5;
}

sass的默认变量一般是用来设置默认值,然后根据需求来覆盖的,覆盖的方式也很简单,只需要在默认变量之前重新声明下变量即可

//sass style
//-------------------------------
$baseLineHeight:        2;
$baseLineHeight:        1.5 !default;
body{
    line-height: $baseLineHeight; 
}

//css style
//-------------------------------
body{
    line-height:2;
}

可以看出现在编译后的line-height为2,而不是我们默认的1.5。默认变量的价值在进行组件化开发的时候会非常有用。

特殊变量

一般我们定义的变量都为属性值,可直接使用,但是如果变量作为属性或在某些特殊情况下等则必须要以#{$variables}形式使用。

//sass style
//-------------------------------
$borderDirection:       top !default; 
$baseFontSize:          12px !default;
$baseLineHeight:        1.5 !default;

//应用于class和属性
.border-#{$borderDirection}{
  border-#{$borderDirection}:1px solid #ccc;
}
//应用于复杂的属性值
body{
    font:#{$baseFontSize}/#{$baseLineHeight};
}

//css style
//-------------------------------
.border-top{
  border-top:1px solid #ccc;
}
body {
  font: 12px/1.5;
}

多值变量

多值变量分为list类型和map类型,简单来说list类型有点像js中的数组,而map类型有点像js中的对象。

list

list数据可通过空格,逗号或小括号分隔多个值,可用nth($var,$index)取值。关于list数据操作还有很多其他函数如length($list)join($list1,$list2,[$separator])append($list,$value,[$separator])等,具体可参考sass Functions(搜索List Functions即可)

定义

//一维数据
$px: 5px 10px 20px 30px;

//二维数据,相当于js中的二维数组
$px: 5px 10px, 20px 30px;
$px: (5px 10px) (20px 30px);

使用

//sass style
//-------------------------------
$linkColor:         #08c #333 !default;//第一个值为默认值,第二个鼠标滑过值
a{
  color:nth($linkColor,1);

  &:hover{
    color:nth($linkColor,2);
  }
}

//css style
//-------------------------------
a{
  color:#08c;
}
a:hover{
  color:#333;
}

map

map数据以key和value成对出现,其中value又可以是list。格式为:$map: (key1: value1, key2: value2, key3: value3);。可通过map-get($map,$key)取值。关于map数据还有很多其他函数如map-merge($map1,$map2)map-keys($map)map-values($map)等,具体可参考sass Functions(搜索Map Functions即可)

定义

$heading: (h1: 2em, h2: 1.5em, h3: 1.2em);

使用

//sass style
//-------------------------------
$headings: (h1: 2em, h2: 1.5em, h3: 1.2em);
@each $header, $size in $headings {
  #{$header} {
    font-size: $size;
  }
}

//css style
//-------------------------------
h1 {
  font-size: 2em; 
}
h2 {
  font-size: 1.5em; 
}
h3 {
  font-size: 1.2em; 
}

全局变量

在变量值后面加上!global即为全局变量。这个目前还用不上,不过将会在sass 3.4后的版本中正式应用。目前的sass变量范围饱受诟病,所以才有了这个全局变量。

目前变量机制

在选择器中声明的变量会覆盖外面全局声明的变量。(这也就人们常说的sass没有局部变量)

//sass style
//-------------------------------
$fontSize:      12px;
body{
    $fontSize: 14px;        
    font-size:$fontSize;
}
p{
    font-size:$fontSize;
}

//css style
//-------------------------------
body{
    font-size:14px;
}
p{
    font-size:14px;
}

启用global之后的机制

请注意,这个目前还无法使用,所以样式不是真实解析出来的。

//sass style
//-------------------------------
$fontSize:      12px;
$color:         #333;
body{
    $fontSize: 14px;        
    $color#fff !global;
    font-size:$fontSize;
    color:$color;
}
p{
    font-size:$fontSize;
    color:$color;
}

//css style
//-------------------------------
body{
    font-size:14px;
    color:#fff;
}
p{
    font-size:12px;
    color:#fff;
}

这里设置了两个变量,然后在body里面重新设置了下,有点不同的是对于$color变量,我们设置了!global。通过编译后的css可以看到font-size取值不同,而color取值相同。与上面的机制对比就会发现默认在选择器里面的变量为局部变量,而只有设置了!global之后才会成为全局变量。

关于变量的详细分析请查阅sass揭秘之变量

嵌套(Nesting)

sass的嵌套包括两种:一种是选择器的嵌套;另一种是属性的嵌套。我们一般说起或用到的都是选择器的嵌套。

选择器嵌套

所谓选择器嵌套指的是在一个选择器中嵌套另一个选择器来实现继承,从而增强了sass文件的结构性和可读性。

在选择器嵌套中,可以使用&表示父元素选择器

//sass style
//-------------------------------
#top_nav{
  line-height: 40px;
  text-transform: capitalize;
  background-color:#333;
  li{
    float:left;
  }
  a{
    display: block;
    padding: 0 10px;
    color: #fff;

    &:hover{
      color:#ddd;
    }
  }
}

//css style
//-------------------------------
#top_nav{
  line-height: 40px;
  text-transform: capitalize;
  background-color:#333;
}  
#top_nav li{
  float:left;
}
#top_nav a{
  display: block;
  padding: 0 10px;
  color: #fff;
}
#top_nav a:hover{
  color:#ddd;
}

属性嵌套

所谓属性嵌套指的是有些属性拥有同一个开始单词,如border-width,border-color都是以border开头。拿个官网的实例看下:

//sass style
//-------------------------------
.fakeshadow {
  border: {
    style: solid;
    left: {
      width: 4px;
      color: #888;
    }
    right: {
      width: 2px;
      color: #ccc;
    }
  }
}

//css style
//-------------------------------
.fakeshadow {
  border-style: solid;
  border-left-width: 4px;
  border-left-color: #888;
  border-right-width: 2px;
  border-right-color: #ccc; 
}

当然这只是个属性嵌套的例子,如果实际这样使用,那估计得疯掉。

@at-root

sass3.3.0中新增的功能,用来跳出选择器嵌套的。默认所有的嵌套,继承所有上级选择器,但有了这个就可以跳出所有上级选择器。

普通跳出嵌套

//sass style
//-------------------------------
//没有跳出
.parent-1 {
  color:#f00;
  .child {
    width:100px;
  }
}

//单个选择器跳出
.parent-2 {
  color:#f00;
  @at-root .child {
    width:200px;
  }
}

//多个选择器跳出
.parent-3 {
  background:#f00;
  @at-root {
    .child1 {
      width:300px;
    }
    .child2 {
      width:400px;
    }
  }
}

//css style
//-------------------------------
.parent-1 {
  color: #f00;
}
.parent-1 .child {
  width: 100px;
}

.parent-2 {
  color: #f00;
}
.child {
  width: 200px;
}

.parent-3 {
  background: #f00;
}
.child1 {
  width: 300px;
}
.child2 {
  width: 400px;
}

@at-root (without: ...)@at-root (with: ...)

默认@at-root只会跳出选择器嵌套,而不能跳出@media@support,如果要跳出这两种,则需使用@at-root (without: media)@at-root (without: support)。这个语法的关键词有四个:all(表示所有),rule(表示常规css),media(表示media),support(表示support,因为@support目前还无法广泛使用,所以在此不表)。我们默认的@at-root其实就是@at-root (without:rule)

//sass style
//-------------------------------
//跳出父级元素嵌套
@media print {
    .parent1{
      color:#f00;
      @at-root .child1 {
        width:200px;
      }
    }
}

//跳出media嵌套,父级有效
@media print {
  .parent2{
    color:#f00;

    @at-root (without: media) {
      .child2 {
        width:200px;
      } 
    }
  }
}

//跳出media和父级
@media print {
  .parent3{
    color:#f00;

    @at-root (without: all) {
      .child3 {
        width:200px;
      } 
    }
  }
}

//sass style
//-------------------------------
@media print {
  .parent1 {
    color: #f00;
  }
  .child1 {
    width: 200px;
  }
}

@media print {
  .parent2 {
    color: #f00;
  }
}
.parent2 .child2 {
  width: 200px;
}

@media print {
  .parent3 {
    color: #f00;
  }
}
.child3 {
  width: 200px;
}

@at-root&配合使用

//sass style
//-------------------------------
.child{
    @at-root .parent &{
        color:#f00;
    }
}

//css style
//-------------------------------
.parent .child {
  color: #f00;
}

应用于@keyframe

//sass style
//-------------------------------
.demo {
    ...
    animation: motion 3s infinite;

    @at-root {
        @keyframes motion {
          ...
        }
    }
}

//css style
//-------------------------------   
.demo {
    ...   
    animation: motion 3s infinite;
}
@keyframes motion {
    ...
}

混合(mixin)

sass中使用@mixin声明混合,可以传递参数,参数名以$符号开始,多个参数以逗号分开,也可以给参数设置默认值。声明的@mixin通过@include来调用。

无参数mixin

//sass style
//-------------------------------
@mixin center-block {
    margin-left:auto;
    margin-right:auto;
}
.demo{
    @include center-block;
}

//css style
//-------------------------------
.demo{
    margin-left:auto;
    margin-right:auto;
}

有参数mixin

//sass style
//-------------------------------   
@mixin opacity($opacity:50) {
  opacity: $opacity / 100;
  filter: alpha(opacity=$opacity);
}

//css style
//-------------------------------
.opacity{
  @include opacity; //参数使用默认值
}
.opacity-80{
  @include opacity(80); //传递参数
}

多个参数mixin

调用时可直接传入值,如@include传入参数的个数小于@mixin定义参数的个数,则按照顺序表示,后面不足的使用默认值,如不足的没有默认值则报错。除此之外还可以选择性的传入参数,使用参数名与值同时传入。

//sass style
//-------------------------------   
@mixin horizontal-line($border:1px dashed #ccc, $padding:10px){
    border-bottom:$border;
    padding-top:$padding;
    padding-bottom:$padding;  
}
.imgtext-h li{
    @include horizontal-line(1px solid #ccc);
}
.imgtext-h--product li{
    @include horizontal-line($padding:15px);
}

//css style
//-------------------------------
.imgtext-h li {
    border-bottom: 1px solid #cccccc;
    padding-top: 10px;
    padding-bottom: 10px;
}
.imgtext-h--product li {
    border-bottom: 1px dashed #cccccc;
    padding-top: 15px;
    padding-bottom: 15px;
}

多组值参数mixin

如果一个参数可以有多组值,如box-shadow、transition等,那么参数则需要在变量后加三个点表示,如$variables...

//sass style
//-------------------------------   
//box-shadow可以有多组值,所以在变量参数后面添加...
@mixin box-shadow($shadow...) {
  -webkit-box-shadow:$shadow;
  box-shadow:$shadow;
}
.box{
  border:1px solid #ccc;
  @include box-shadow(0 2px 2px rgba(0,0,0,.3),0 3px 3px rgba(0,0,0,.3),0 4px 4px rgba(0,0,0,.3));
}

//css style
//-------------------------------
.box{
  border:1px solid #ccc;
  -webkit-box-shadow:0 2px 2px rgba(0,0,0,.3),0 3px 3px rgba(0,0,0,.3),0 4px 4px rgba(0,0,0,.3);
  box-shadow:0 2px 2px rgba(0,0,0,.3),0 3px 3px rgba(0,0,0,.3),0 4px 4px rgba(0,0,0,.3);
}

@content

@content在sass3.2.0中引入,可以用来解决css3的@media等带来的问题。它可以使@mixin接受一整块样式,接受的样式从@content开始。

 //sass style
//-------------------------------                     
@mixin max-screen($res){
  @media only screen and ( max-width: $res )
  {
    @content;
  }
}

@include max-screen(480px) {
  body { color: red }
}

//css style
//-------------------------------
@media only screen and (max-width: 480px) {
  body { color: red }
}                     

PS:@mixin通过@include调用后解析出来的样式是以拷贝形式存在的,而下面的继承则是以联合声明的方式存在的,所以从3.2.0版本以后,建议传递参数的用@mixin,而非传递参数类的使用下面的继承%

继承

sass中,选择器继承可以让选择器继承另一个选择器的所有样式,并联合声明。使用选择器的继承,要使用关键词@extend,后面紧跟需要继承的选择器。

//sass style
//-------------------------------
h1{
  border: 4px solid #ff9aa9;
}
.speaker{
  @extend h1;
  border-width: 2px;
}

//css style
//-------------------------------
h1,.speaker{
  border: 4px solid #ff9aa9;
}
.speaker{
  border-width: 2px;
}

占位选择器%

从sass 3.2.0以后就可以定义占位选择器%。这种选择器的优势在于:如果不调用则不会有任何多余的css文件,避免了以前在一些基础的文件中预定义了很多基础的样式,然后实际应用中不管是否使用了@extend去继承相应的样式,都会解析出来所有的样式。占位选择器以%标识定义,通过@extend调用。

//sass style
//-------------------------------
%ir{
  color: transparent;
  text-shadow: none;
  background-color: transparent;
  border: 0;
}
%clearfix{
  @if $lte7 {
    *zoom: 1;
  }
  &:before,
  &:after {
    content: "";
    display: table;
    font: 0/0 a;
  }
  &:after {
    clear: both;
  }
}
#header{
  h1{
    @extend %ir;
    width:300px;
  }
}
.ir{
  @extend %ir;
}

//css style
//-------------------------------
#header h1,
.ir{
  color: transparent;
  text-shadow: none;
  background-color: transparent;
  border: 0;
}
#header h1{
  width:300px;
}

如上代码,定义了两个占位选择器%ir%clearfix,其中%clearfix这个没有调用,所以解析出来的css样式也就没有clearfix部分。占位选择器的出现,使css文件更加简练可控,没有多余。所以可以用其定义一些基础的样式文件,然后根据需要调用产生相应的css。

ps:在@media中暂时不能@extend @media外的代码片段,以后将会可以。

函数

sass定义了很多函数可供使用,当然你也可以自己定义函数,以@fuction开始。sass的官方函数链接为:sass fuction,实际项目中我们使用最多的应该是颜色函数,而颜色函数中又以lighten减淡和darken加深为最,其调用方法为lighten($color,$amount)darken($color,$amount),它们的第一个参数都是颜色值,第二个参数都是百分比。

//sass style
//-------------------------------                     
$baseFontSize:      10px !default;
$gray:              #ccc !defualt;        

// pixels to rems 
@function pxToRem($px) {
  @return $px / $baseFontSize * 1rem;
}

body{
  font-size:$baseFontSize;
  color:lighten($gray,10%);
}
.test{
  font-size:pxToRem(16px);
  color:darken($gray,10%);
}

//css style
//-------------------------------
body{
  font-size:10px;
  color:#E6E6E6;
}
.test{
  font-size:1.6rem;
  color:#B3B3B3;
}

关于@mixin%@function更多说明可参阅:

运算

sass具有运算的特性,可以对数值型的Value(如:数字、颜色、变量等)进行加减乘除四则运算。请注意运算符前后请留一个空格,不然会出错。

$baseFontSize:          14px !default;
$baseLineHeight:        1.5 !default;
$baseGap:               $baseFontSize * $baseLineHeight !default;
$halfBaseGap:           $baseGap / 2  !default;
$samllFontSize:         $baseFontSize - 2px  !default;

//grid 
$_columns:                     12 !default;      // Total number of columns
$_column-width:                60px !default;   // Width of a single column
$_gutter:                      20px !default;     // Width of the gutter
$_gridsystem-width:            $_columns * ($_column-width + $_gutter); //grid system width

条件判断及循环

@if判断

@if可一个条件单独使用,也可以和@else结合多条件使用

//sass style
//-------------------------------
$lte7: true;
$type: monster;
.ib{
    display:inline-block;
    @if $lte7 {
        *display:inline;
        *zoom:1;
    }
}
p {
  @if $type == ocean {
    color: blue;
  } @else if $type == matador {
    color: red;
  } @else if $type == monster {
    color: green;
  } @else {
    color: black;
  }
}

//css style
//-------------------------------
.ib{
    display:inline-block;
    *display:inline;
    *zoom:1;
}
p {
  color: green; 
}

三目判断

语法为:if($condition, $if_true, $if_false) 。三个参数分别表示:条件,条件为真的值,条件为假的值。

if(true, 1px, 2px) => 1px
if(false, 1px, 2px) => 2px

for循环

for循环有两种形式,分别为:@for $var from <start> through <end>@for $var from <start> to <end>。$i表示变量,start表示起始值,end表示结束值,这两个的区别是关键字through表示包括end这个数,而to则不包括end这个数。

//sass style
//-------------------------------
@for $i from 1 through 3 {
  .item-#{$i} { width: 2em * $i; }
}

//css style
//-------------------------------
.item-1 {
  width: 2em; 
}
.item-2 {
  width: 4em; 
}
.item-3 {
  width: 6em; 
}

@each循环

语法为:@each $var in <list or map>。其中$var表示变量,而list和map表示list类型数据和map类型数据。sass 3.3.0新加入了多字段循环和map数据循环。

单个字段list数据循环

//sass style
//-------------------------------
$animal-list: puma, sea-slug, egret, salamander;
@each $animal in $animal-list {
  .#{$animal}-icon {
    background-image: url('/images/#{$animal}.png');
  }
}

//css style
//-------------------------------
.puma-icon {
  background-image: url('/images/puma.png'); 
}
.sea-slug-icon {
  background-image: url('/images/sea-slug.png'); 
}
.egret-icon {
  background-image: url('/images/egret.png'); 
}
.salamander-icon {
  background-image: url('/images/salamander.png'); 
}

多个字段list数据循环

//sass style
//-------------------------------
$animal-data: (puma, black, default),(sea-slug, blue, pointer),(egret, white, move);
@each $animal, $color, $cursor in $animal-data {
  .#{$animal}-icon {
    background-image: url('/images/#{$animal}.png');
    border: 2px solid $color;
    cursor: $cursor;
  }
}

//css style
//-------------------------------
.puma-icon {
  background-image: url('/images/puma.png');
  border: 2px solid black;
  cursor: default; 
}
.sea-slug-icon {
  background-image: url('/images/sea-slug.png');
  border: 2px solid blue;
  cursor: pointer; 
}
.egret-icon {
  background-image: url('/images/egret.png');
  border: 2px solid white;
  cursor: move; 
}

多个字段map数据循环

//sass style
//-------------------------------
$headings: (h1: 2em, h2: 1.5em, h3: 1.2em);
@each $header, $size in $headings {
  #{$header} {
    font-size: $size;
  }
}

//css style
//-------------------------------
h1 {
  font-size: 2em; 
}
h2 {
  font-size: 1.5em; 
}
h3 {
  font-size: 1.2em; 
}

关于循环判断详细分析请查阅:sass揭秘之@if,@for,@each

Sass基础——Sass函数

   在Sass中除了可以定义变量,具有@extend,%placeholders和Mixins等特性之外,还自备了一系列的函数功能。前面在《Sass基础——颜色函数》一文中主要向大家介绍了Sass函数中有关于颜色函数的功能以及使用。其实在Sass的函数功能中除了颜色函数之外,还具有字符串函数数字函数列表函数Introspection函数以及三元函数等,当然大家还可以根据需求自定义函数

在这篇文章中,我们主要对Sass函数中的字符串函数数字函数列表函数Introspection函数以及三元函数的功能能使用做一些简单的介绍,希望对初学Sass的同学略有帮助。

字符串函数

字符串函数顾名思意是用来处理字符串的函数。Sass的字符串函数主要包括两个函数:

unquote()函数

unquote()函数主要是用来删除一个字符串中的引号,如果这个字符串没有带有引号,将返回原始的字符串。简单的使用终端来测试这个函数的运行结果:

//SCSS
.test1 {
    content:  unquote('Hello Sass!') ;
}
.test2 {
    content: unquote("'Hello Sass!");
}
.test3 {
    content: unquote("I'm Web Designer");
}
.test4 {
    content: unquote("'Hello Sass!'");
}
.test5 {
    content: unquote('"Hello Sass!"');
}
.test6 {
    content: unquote(Hello Sass);
}

//CSS
.test1 {
  content: Hello Sass!; }

.test2 {
  content: 'Hello Sass!; }

.test3 {
  content: I'm Web Designer; }

.test4 {
  content: 'Hello Sass!'; }

.test5 {
  content: "Hello Sass!"; }

.test6 {
  content: Hello Sass; }

从测试的效果中可以看出,unquote()函数只能删除字符串最前和最后的引号(双引号或单引号),而无法删除字符串中间的引号。如果字符没有带引号,返回的将是字符串本身。

quote()函数

quote()函数刚好与unquote()函数功能相反,主要用来给字符串添加引号。如果字符串,自身带有引号会统一换成双引号""。如:

//SCSS
.test1 {
    content:  quote('Hello Sass!');
}
.test2 {
    content: quote("Hello Sass!");
}
.test3 {
    content: quote(ImWebDesigner);
}
.test4 {
    content: quote(' ');
}
//CSS
.test1 {
  content: "Hello Sass!"; 
}

.test2 {
  content: "Hello Sass!"; 
}

.test3 {
  content: "ImWebDesigner"; 
}
.test4 {
  content: " "; 
}

使用quote()函数增加只能给字符串增加双引号,而且字符串中间有单引号或者空格时,需要用单引号或双引号括起,否则编译的时候将会报错。

.test1 {
    content:  quote(Hello Sass);
}

这样使用,编译器马上会报错:

error style.scss (Line 13: $string: ("Hello" "Sass") is not a string for `quote')

解决方案就是去掉空格,或者加上引号:

.test1 {
    content:  quote(HelloSass);
}
.test1 {
    content:  quote("Hello Sass");
}

同时quote()碰到特殊符号,比如说!?>等,除中折号-和下划线_都需要使用双引号括起,否则编译器在进行编译的时候同样会报错:

error style.scss (Line 13: Invalid CSS after "...quote(HelloSass": expected ")", was "!);")
error style.scss (Line 16: Invalid CSS after "...t:  quote(Hello": expected ")", was "?);")

数字函数

Sass中的数字函数提要针对数字方面提供一系列的函数功能:

看到上面函数的简介,对于熟悉javascript同学而言并不会感觉陌生。因为他们有很多功能都非常类似,接下来对每个函数进行一些简单的测试。

percentage()

percentage()函数主要是将一个不带单位的数字转换成百分比形式:

>> percentage(.2)
20%
>> percentage(2px / 10px)
20%
>> percentage(2em / 10em)
20%
>>

如果您转换的值是一个带有单位的值,那么在编译的时候会报错误信息:

>> percentage(2px / 10em)
SyntaxError: $value: 0.2px/em is not a unitless number for `percentage'

round()函数

round()函数将一个数四舍五入为一个最接近的整数:

>> round(12.3)
12
>> round(12.5)
13
>> round(1.49999)
1
>> round(2.0)
2
>> round(20%)
20%
>> round(2.2%)
2%
>> round(3.9em)
4em
>> round(2.3px)
2px
>> round(2px / 3px)
1
>> round(1px / 3px)
0
>> round(3px / 2em)
2px/em

round()函数中可以携带单位的任何数值。

ceil()函数

ceil()函数将一个数转换成最接近于自己的整数,会将一个大于自身的任何小数转换成大于本身1的整数。也就是只做入,不做舍的计算:

>> ceil(2.0)
2
>> ceil(2.1)
3
>> ceil(2.6)
3
>> ceil(2.3%)
3%
>> ceil(2.3px)
3px
>> ceil(2.5px)
3px
>> ceil(2px / 3px)
1
>> ceil(2% / 3px)
1%/px
>> ceil(1em / 5px)
1em/px

floor()函数

floor()函数刚好与ceil()函数功能相反,其主要将一个数去除其小数部分,并且不做任何的进位。也就是只做舍,不做入的计算:

>> floor(2.1)
2
>> floor(2.5)
2
>> floor(3.5%)
3%
>> floor(10.2px)
10px
>> floor(10.8em)
10em
>> floor(2px / 10px)
0
>> floor(3px / 1em)
3px/em

abs()函数

abs()函数会返回一个数的绝对值。

>> abs(10)
10
>> abs(-10)
10
>> abs(-10px)
10px
>> abs(-2em)
2em
>> abs(-.5%)
0.5%
>> abs(-1px / 2px)
0.5

min()函数

min()函数功能主要是在多个数之中找到最小的一个,这个函数可以设置任意多个参数:

>> min(1,2,1%,3,300%)
1%
>> min(1px,2,3px)
1px
>> min(1em,2em,6em)
1em

不过在min()函数中同时出现两种不同类型的单位,将会报错误信息:

>> min(1px,1em)
SyntaxError: Incompatible units: 'em' and 'px'.

max()函数

max()函数和min()函数一样,不同的是,max()函数用来获取一系列数中的最大那个值:

>> max(1,5)
5
>> max(1px,5px)
5px

同样的,如果在max()函数中有不同单位,将会报错:

>> max(1,3px,5%,6)
SyntaxError: Incompatible units: '%' and 'px'.

List函数

列表函数主要包括一些对列表参数的函数使用,主要包括以下几种:

列表函数中的每个函数都有其独特的作用与功能,接下来我们通过命令终端向大家展示每个列表函数的功能与使用。

length()函数

length()函数主要用来返回一个列表中有几个值,简单点说就是返回列表清单中有多少个值:

>> length(10px)
1
>> length(10px 20px (border 1px solid) 2em)
4
>> length(border 1px solid)
3

length()函数中的列表参数之间使用空格隔开,不能使用逗号,否则函数将会把错:

>> length(10px,20px,(border 1px solid),2em)
SyntaxError: wrong number of arguments (4 for 1) for `length'
>> length(1,2px)
SyntaxError: wrong number of arguments (2 for 1) for `length'

nth()函数

nth()函数用来指定列表中某个位置的值。不过在Sass中,nth()函数和其他语言不同,1是指列表中的第一个标签值,2是指列给中的第二个标签值,依此类推。如:

>> nth(10px 20px 30px,1)
10px
>> nth((Helvetica,Arial,sans-serif),2)
"Arial"
>> nth((1px solid red) border-top green,1)
(1px "solid" #ff0000)

注:nth($list,$n)函数中的$n必须是大于0的整数:

>> nth((1px solid red) border-top green 1 ,0)
SyntaxError: List index 0 must be a non-zero integer for `nth'

join()函数

join()函数是将两个列表连接合并成一个列表。

>> join(10px 20px, 30px 40px)
(10px 20px 30px 40px)
>> join((blue,red),(#abc,#def))
(#0000ff, #ff0000, #aabbcc, #ddeeff)
>> join((blue,red),(#abc #def))
(#0000ff, #ff0000, #aabbcc, #ddeeff)

不过join()只能将两个列表连接成一个列表,如果直接连接两个以上的列表将会报错:

>> join((blue red),(#abc, #def),(#dee #eff))
SyntaxError: $separator: (#ddeeee #eeffff) is not a string for `join'

但很多时候不只碰到两个列表连接成一个列表,这个时候就需要将多个join()函数合并在一起使用:

>> join((blue red), join((#abc #def),(#dee #eff)))
(#0000ff #ff0000 #aabbcc #ddeeff #ddeeee #eeffff)

join()函数中还有一个很有特别的参数$separator,这个参数主要是用来给列表函数连接列表值是,使用的分隔符号,默认值为auto

join()函数中$separator除了默认值auto之外,还有commaspace两个值,其中comma值指定列表中的列表项值之间使用逗号,)分隔,space值指定列表中的列表项值之间使用空格( )分隔。

join()函数中除非明确指定了$separator值,否则将会有多种情形发生:

如果列表中的第一个列表中每个值之间使用的是逗号(,),那么join()函数合并的列表中每个列表项之间使用逗号,分隔:

>> join((blue, red, #eff),(green orange))
(#0000ff, #ff0000, #eeffff, #008000, #ffa500)

但当第一个列表中只有一个列表项,那么join()函数合并的列表项目中每个列表项目这间使用的分隔符号会根据第二个列表项中使用的,如果第二列表项中使用是,分隔,则使用逗号分隔;如果第二列项之间使用的空格符,则使用空格分隔:

>> join(blue,(green, orange))
(#0000ff, #008000, #ffa500)
>> join(blue,(green orange))
(#0000ff #008000 #ffa500)

如果列表中的第一个列表中每个值之间使用的是空格,那么join()函数合并的列表中每个列表项之间使用空格分隔:

>> join((blue green),(red,orange))
(#0000ff #008000 #ff0000 #ffa500)
>> join((blue green),(red orange))
(#0000ff #008000 #ff0000 #ffa500)

如果当两个列表中的列表项小于1时,将会以空格分隔:

>> join(blue,red)
(#0000ff #ff0000)

如此一来,会有多种情形发生,造成使用混乱的情形,如果你无法记得,什么时候会是用逗号分隔合并的列表项,什么时候是使用空格分隔合并的列表项,在些建议大家使用join()函数合并列表项的时候就明确指定$separator参数,用来指定合并的列表中使用什么方式来分隔列表项:

>> join(blue,red,comma)
(#0000ff, #ff0000)
>> join(blue,red,space)
(#0000ff #ff0000)
>> join((blue green),(red,orange),comma)
(#0000ff, #008000, #ff0000, #ffa500)
>> join((blue green),(red,orange),space)
(#0000ff #008000 #ff0000 #ffa500)
>> join((blue, green),(red,orange),comma)
(#0000ff, #008000, #ff0000, #ffa500)
>> join((blue, green),(red,orange),space)
(#0000ff #008000 #ff0000 #ffa500)
>> join(blue,(red,orange),comma)
(#0000ff, #ff0000, #ffa500)
>> join(blue,(red,orange),space)
(#0000ff #ff0000 #ffa500)
>> join(blue,(red orange),comma)
(#0000ff, #ff0000, #ffa500)
>> join(blue,(red orange),space)
(#0000ff #ff0000 #ffa500)

append()函数

append()函数是用来将某个值插入到列表中,并且处于最末位。

>> append(10px 20px ,30px)
(10px 20px 30px)
>> append((10px,20px),30px)
(10px, 20px, 30px)
>> append(green,red)
(#008000 #ff0000)
>> append(red,(green,blue))
(#ff0000 (#008000, #0000ff))

如果没有明确的指定$separator参数值,其默认值是auto。如果列表只有一个列表项时,那么插入进来的值将和原来的值会以空格的方式分隔。如果列表中列表项是以空格分隔列表项,那么插入进来的列表项也将以空格分隔;如果列表中列表项是以逗号分隔列表项,那么插入进来的列表项也将以逗号分隔。

当然,在append()函数中,可以显示的设置$separator参数,如果取值为comma将会以逗号分隔列表项,如果取值为space将会以空格分隔列表项:

>> append((blue green),red,comma)
(#0000ff, #008000, #ff0000)
>> append((blue green),red,space)
(#0000ff #008000 #ff0000)
>> append((blue, green),red,comma)
(#0000ff, #008000, #ff0000)
>> append((blue, green),red,space)
(#0000ff #008000 #ff0000)
>> append(blue,red,comma)
(#0000ff, #ff0000)
>> append(blue,red,space)
(#0000ff #ff0000)

zip()函数

zip()函数将多个列表值转成一个多维的列表:

>> zip(1px 2px 3px,solid dashed dotted,green blue red)
((1px "solid" #008000), (2px "dashed" #0000ff), (3px "dotted" #ff0000))

在使用zip()函数时,每个单一的列表个数值必须是相同的:

>> zip(1px 2px 3px, solid , green blue red)
NoMethodError: undefined method `options=' for nil:NilClass
  Use --trace for backtrace.

否则将会出错。

zip()函数中每个单一列表的值对应的取其相同位置值:

|--- List ---|--- nth(1) ---|--- nth(2) ---|--- nth(3) ---|
|------------|--------------|--------------|--------------|
|    List1   |      1px     |      2px     |      3px     |
|------------|--------------|--------------|--------------|
|    List2   |      solid   |      dashed  |     dotted   |
|------------|--------------|--------------|--------------|
|    List3   |      green   |      blue    |      red     |
|------------|--------------|--------------|--------------|

zip()函数组合出来就成了:

1px solid green, 2px dashed blue, 3px dotted red

index()函数

index()函数类似于索引一样,主要让你找到某个值在列表中所处的位置。在Sass中,第一个值就是1,第二个值就是2,依此类推:

>> index(1px solid red, 1px)
1
>> index(1px solid red, solid)
2
>> index(1px solid red, red)
3

index()函数中,如果指定的值不在列表中(没有找到相应的值),那么返回的值将是false,相反就会返回对应的值在列表中所处的位置。

>> index(1px solid red,dotted) //列表中没有找到dotted
false
>> index(1px solid red,solid) //列表中找到solid值,并且返回他的位置值2
2

Introspection函数

Introspection函数包括了几个判断型函数:

这几个函数主要用来对值做一个判断的作用,依次来看每个函数的功能。

type-of()函数

type-of()函数主要用来判断一个值是属于什么类型:

>> type-of(100)
"number"
>> type-of(100px)
"number"
>> type-of("asdf")
"string"
>> type-of(asdf)
"string"
>> type-of(true)
"bool"
>> type-of(false)
"bool"
>> type-of(#fff)
"color"
>> type-of(blue)
"color"
>> type-of(1 / 2 = 1)
"string"

unit()函数

unit()函数主要是用来获取一个值所使用的单位,碰到复杂的计算时,其能根据运算得到一个多单位组合的值,不过只充许乘除运算:

>> unit(100)
""
>> unit(100px)
"px"
>> unit(20%)
"%"
>> unit(1em)
"em"
>> unit(10px * 3em)
"em*px"
>> unit(10px / 3em)
"px/em"
>> unit(10px * 2em / 3cm / 1rem)
"em/rem"

但加减碰到不同单位时,unit()函数将会报错,除pxcmmm运算之外:

>> unit(1px + 1cm)
"px"
>> unit(1px - 1cm)
"px"
>> unit(1px + 1mm)
"px"
>> unit(10px * 2em - 3cm / 1rem)
SyntaxError: Incompatible units: 'cm' and 'px*em'.
>> unit(10px * 2em - 1px / 1rem)
SyntaxError: Incompatible units: '' and 'em'.
>> unit(1px - 1em)
SyntaxError: Incompatible units: 'em' and 'px'.
>> unit(1px - 1rem)
SyntaxError: Incompatible units: 'rem' and 'px'.
>> unit(1px - 1%)
SyntaxError: Incompatible units: '%' and 'px'.
>> unit(1cm + 1em)
SyntaxError: Incompatible units: 'em' and 'cm'.

unit()函数对于单位运算相对来说也没有规律,而且有些单位也无法整合成一个单位,对于我们在CSS中运用中并不适合,比如:

>> unit(10px * 3em)
"em*px"
>> unit(10px / 3em)
"px/em"
>> unit(10px * 2em / 3cm / 1rem)
"em/rem"

换句话说,上面运算出来的单位,对于在CSS中使用将是没有任何意义的。

unitless()函数

unitless()函数相对来说简单明了些,只是用来判断一个值是否带有单位,如果不带单位返回的值为true,带单位返回的值为false

>> unitless(100)
true
>> unitless(100px)
false
>> unitless(100em)
false
>> unitless(100%)
false
>> unitless(1 /2 )
true
>> unitless(1 /2 + 2 )
true
>> unitless(1px /2 + 2 )
false

comparable()函数

comparable()函数主要是用来判断两个数是否可以进行加,减以及合并。如果可以返回的值为true,如果不可以返回的值是false

>> comparable(2px,1px)
true
>> comparable(2px,1%)
false
>> comparable(2px,1em)
false
>> comparable(2rem,1em)
false
>> comparable(2px,1cm)
true
>> comparable(2px,1mm)
true
>> comparable(2px,1rem)
false
>> comparable(2cm,1mm)
true

Miscellaneous函数

在这里把Miscellaneous函数称为三元条件函数,主要因为他和JavaScript中的三元判断非常的相似。他有两个值,当条件成立返回一种值,当条件不成立时返回另一种值:

if($condition,$if-true,$if-false)

上面表达式的意思是当$condition条件成立时,返回的值为$if-true,否则返回的是$if-false值。

>> if(true,1px,2px)
1px
>> if(false,1px,2px)
2px

自定义函数

自定义函数是用户根据自己一些特殊的需求编写的Sass函数。在很多时候,Sass自带的函数并不能满足功能上的需求,所以很多时候需要自定义一些函数。

例如,我们需要去掉一个值的单位,在这种情形之下,Sass自带的函数是无法帮助我们完成,这个时候我们就需要定义函数:

//去掉一个值的单位,如12px => 12
// eg. strip-units(12px) => 12

@function strip-units($number){
    @return $number / ($number * 0 + 1);
}     

上在演示是一个经典的去除单位的自定义函数,除了这个函数之外,大家还可以根据自己需求定义其他的函数,正如前面介绍的pxToempxTorem两个自定义的函数。

总结

在这一节中,主要根据Sass的官网介绍的函数为范本,借助Sass的sass -i命令在终端向大家展示了Sass函数中的字符串函数数字函数列表函数Introspection函数以及三元函数等功能以及使用方法。并且在最后简单的介绍了在Sass中如何自定义Sass的函数。希望这篇文章对于初学者能更好的理解Sass中的自带函数的功能与作用。

转载:http://www.w3cplus.com/preprocessor/sass-other-function.html