less在处理CSS动画时,非常恶心,决定转向sass了。sass诞生得比less早,只是因为它是ruby写的,因此受众面够少。但我们不需要自己下编译器或使用命令行,我们可以koala这神器
首先几个注意点,sass可以用sass后缀名,也可以用scss后缀名。前者比较恶心,像python一样没有花括号,也不让写分号,散架子一样。因此推荐用scss,这个也是目前我遇到的大部分人的选择。
关于中文编译出错的问题,需要指定字符集。
@charset "utf-8";//必须设置了这个才能编译有中文的注释 $fontSize: 12px; body{ font-size:$fontSize; } /* 测试注释 */ $side : left; .rounded { border-#{$side}-radius: 5px; }
注释的问题,sass有两种注释方式,一种是标准的css注释方式/* */,另一种则是//双斜杆形式的单行注释,不过这种单行注释不会被转译出来。
导入的问题,它还是用@import关键字,但做了一些处理,如果后缀名是css,那么它不会对此导入文件进行编译,如果是sass,scss或没有写,那么就会编译。
@import "reset.css"; @import "a"; p{ background: #0982c1; }
好了,我们正式开始学习它的语法。sass既然是一门正统的编程语言,就有对应的变量,数据结构,函数等东西。
sass使用PHP风格的$开头的变量命名风格,使用ruby风格#{ }占位符
@charset "utf-8";//必须设置了这个才能编译有中文的注释 $borderDirection: top !default; $fontSize: 12px !default; $baseLineHeight: 1.5 !default; //应用于class和属性 .border-#{$borderDirection}{ border-#{$borderDirection}:1px solid #ccc; } //应用于复杂的属性值 body{ font:#{$fontSize}/#{$baseLineHeight}; } $base: ".module"; #{$base} { {$base}-something { background: red; } } //------------------------------- .border-top { border-top: 1px solid #ccc; } body { font: 12px/1.5; } .module.module-something { background: red; }
变量与占位符,可以让我们构建复杂可重用的属性值。
默认值,写法有点类似!important,但优先级最低。
$baseLineHeight: 2; $baseLineHeight: 1.5 !default; body{ line-height: $baseLineHeight; } //------------------------------- body{ line-height:2; }
编译后的line-height为2,而不是我们默认的1.5。默认变量的价值在进行组件化开发的时候会非常有用。
数据结构方面,它拥有类似数组的list类型,类似对象的map类型
sass的数组,是通过空格来划分元素,如果是二维组数,则需要用到小括号与逗号。
//一维数组 $array: 5px 10px 20px 30px; //二维数组 $array2: 5px 10px, 20px 30px; $array3: (5px 10px) (20px 30px);
sass的数组有一个特点,没有用[]包起来,也不能用[]来取其中的某一个元素,要用需要用到nth内置方法,并且nth与CSS3的nth-child一样,是从1开始。
$linkColor: #08c #333 #ccc; a{ color:nth($linkColor,1); &:hover{ color:nth($linkColor,2); } } //css style //------------------------------- a{ color:#08c; } a:hover{ color:#333; }
相关操作数组的方法
创建一个空数组 $list:(); join($list1, $list2, $separator:auto) //合并两个数组 join(10px 20px, 30px 40px) => 10px 20px 30px 40px join((blue, red), (#abc, #def)) => blue, red, #abc, #def join(10px, 20px) => 10px 20px join(10px, 20px, comma) => 10px, 20px join((blue, red), (#abc, #def), space) => blue red #abc #def index($list, $value) //取得目标在数组的位置,以1开始 index(1px solid red, solid) => 2 index(1px solid red, dashed) => null index(( 10px, height: 20px), (height 20px)) => 2 length($list) //取得数组的长度 length(10px) => 1 length(10px 20px 30px) => 3 length(( 10px, height: 20px)) => 2 list_separator($list) //取得数组的分隔符 list-separator(1px 2px 3px) => space list-separator(1px, 2px, 3px) => comma list-separator('foo') => space nth($list, $n) //取得数组在某一位置上的元素 nth(10px 20px 30px, 1) => 10px nth((Helvetica, Arial, sans-serif), 3) => sans-serif nth(( 10px, length: 20px), 2) => length, 20px zip(*$lists) //将多个$list组合在一起成为一个多维列表。如果列表源长度并不是所有都相同,结果列表长度将以最短的一个为准 append($list, $val, $separator:auto) append(10px 20px, 30px) => 10px 20px 30px append((blue, red), green) => blue, red, green append(10px 20px, 30px 40px) => 10px 20px (30px 40px) append(10px, 20px, comma) => 10px, 20px append((blue, red), green, space) => blue red green
sass的对象与JS的对象很相似,唯一不同的是,它是用小括号括起来,因为花括号用作各种嵌套边界。同时,为了操作sass对象,它提供了比JS丰富多的函数,它们基本是以map-开头(全部小写并且用“-”连起来是纯正的ruby风格)。
$heading: (h1: 2em, h2: 1.5em, h3: 1.2em);
下面是方法演示
map-get //取得对象的某一属性的值 map-get(("foo": 1, "bar": 2), "foo") => 1 map-get(("foo": 1, "bar": 2), "bar") => 2 map-get(("foo": 1, "bar": 2), "baz") => null map-remove($map, $key) //删掉某一键值对 map-remove(("foo": 1, "bar": 2), "bar") => ("foo": 1) map-remove(("foo": 1, "bar": 2), "baz") => ("foo": 1, "bar": 2) map-keys($map) //取得它的所有属性名,以数组形式返回 map-keys(("foo": 1, "bar": 2)) => "foo", "bar" map-values($map) //取得它的所有属性值,以数组形式返回 map-values(("foo": 1, "bar": 2)) => 1, 2 map-values(("foo": 1, "bar": 2, "baz": 1)) => 1, 2, 1 map-has-key($map, $key) //判定它是否拥有某一个属性 map-has-key(("foo": 1, "bar": 2), "foo") => true map-has-key(("foo": 1, "bar": 2), "baz") => false map-merge($map1, $map2) //合并两个对象 map-merge(("foo": 1), ("bar": 2)) => ("foo": 1, "bar": 2) map-merge(("foo": 1, "bar": 2), ("bar": 3)) => ("foo": 1, "bar": 3)
流程控制: @if,@else, @for,@each和@while
@if非常简单,我们直接看例子
@charset "utf-8";//必须设置了这个才能编译有中文的注释 $boolean: true !default; @mixin simple-mixin { @if $boolean { display: block; } @else { display: none; } } .some-selector { @include simple-mixin; } //------------------------------ .some-selector { display: block; }
说到这个,sass有一个if内置方法,用于模拟三目运算符。
@if $width != auto { $ if(unitless($width), $width + px, $width); }
@for有两种形式, @for xxx form yyy through zzz或@for xxx form yyy to zzz,需要用户指定开始值与结束值,它们都应该是数字。
@charset "utf-8";//必须设置了这个才能编译有中文的注释 $name: for !default; //相当于JS的 for(var $i = 1; $i <= 4; $i++){} @for $i from 1 through 4 { .#{$name}-#{$i}{ 60px + $i; } } //------------------------------ .for-1 { 61px; } .for-2 { 62px; } .for-3 { 63px; } .for-4 { 64px; }
@charset "utf-8";//必须设置了这个才能编译有中文的注释 $name: for !default; //相当于JS的 for(var $i = 1; $i < 4; $i++){} @for $i from 1 to 4 { .#{$name}-#{$i}{ 60px + $i; } } //------------------------------ .for-1 { 61px; } .for-2 { 62px; } .for-3 { 63px; }
@for循环指令除了可以从小数值到大数值循环之外,还可以从大数值循环到小数值。而且两种形式都支持。
@charset "utf-8";//必须设置了这个才能编译有中文的注释 $name: for !default; //由于开始值大于结束值,因此是递减,相当于for(var $e = 5; $e >= 1; $e--){} @for $e from 5 through 1 { .#{$name}-#{$e}{ 60px + $e; } } //------------------------------ .for-5 { 65px; } .for-4 { 64px; } .for-3 { 63px; } .for-2 { 62px; } .for-1 { 61px; }
@each 是用于遍历数组与对象的。
如果是遍历数组, @each跟着的是元素的变量名,随便起,接着是in,最后是数组名。
@charset "utf-8";//必须设置了这个才能编译有中文的注释 $list: adam john wynn mason kuroir; @mixin author-images { @each $author in $list { .photo-#{$author} { background: url("/images/avatars/#{$author}.png") no-repeat; } } } .author-bio { @include author-images; } //------------------------------ .author-bio .photo-adam { background: url("/images/avatars/adam.png") no-repeat; } .author-bio .photo-john { background: url("/images/avatars/john.png") no-repeat; } .author-bio .photo-wynn { background: url("/images/avatars/wynn.png") no-repeat; } .author-bio .photo-mason { background: url("/images/avatars/mason.png") no-repeat; } .author-bio .photo-kuroir { background: url("/images/avatars/kuroir.png") no-repeat; } //================================ @charset "utf-8";//必须设置了这个才能编译有中文的注释 //循环二维数组 $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; } } //------------------------------- .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; }
@charset "utf-8";//必须设置了这个才能编译有中文的注释 $icon-glass: "f000";//批量生成ICON字体 $icon-music: "f001"; $icon-search: "f002"; $icon-envelope-o: "f003"; $icon-heart: "f004"; $icon-star: "f005"; $icon_names: icon-glass icon-music icon-search icon-envelope-o icon-heart icon-star; $icon_vars: $icon-glass $icon-music $icon-search $icon-envelope-o $icon-heart $icon-star; @each $name in $icon_names { $i: index($icon_names, $name); .#{$name} { content: nth($icon_vars, $i); } } //------------------------------ .icon-glass { content: "f000"; } .icon-music { content: "f001"; } .icon-search { content: "f002"; } .icon-envelope-o { content: "f003"; } .icon-heart { content: "f004"; } .icon-star { content: "f005"; }
上面的优化版
@charset "utf-8";//必须设置了这个才能编译有中文的注释 $icons: glass "f000", music "f001", search "f002", envelope-o "f003", heart "f004", star "f005" ;//定义一个2维数组 @function get-icon($icon-name){//要什么生产什么,不需要一下子全部生成出来 @each $icon in $icons { @if nth($icon, 1) == $icon-name { @return nth($icon,2); } } } .icon-glass { content: get-icon(glass); } //------------------------------ .icon-glass { content: "f000"; }
@charset "utf-8";//必须设置了这个才能编译有中文的注释 $icons: ( glass :"f000", music: "f001", search: "f002", envelope-o: "f003", heart: "f004", star: "f005" ); @function get-icon($icon-name){//要什么生产什么,不需要一下子全部生成出来 @return map-get($icons, $icon-name); } .icon-glass { content: get-icon(glass); } //------------------------------ .icon-glass { content: "f000"; }
如果是遍历对象,后面跟着两个变量,分别是键名与键值,逗号隔开,接着是in,最后是对象名。
@charset "utf-8";//必须设置了这个才能编译有中文的注释 @each $key, $val in (h1: 2em, h2: 1.5em, h3: 1.2em) { #{$key} { font-size: $val; } } //------------------------------ h1 { font-size: 2em; } h2 { font-size: 1.5em; } h3 { font-size: 1.2em; }
@while与JS的while非常相似
@charset "utf-8";//必须设置了这个才能编译有中文的注释 $types: 4; $type- 20px; @while $types > 0 { .while-#{$types} { $type-width + $types; } $types: $types - 1; } //------------------------------ .while-4 { 24px; } .while-3 { 23px; } .while-2 { 22px; } .while-1 { 21px; }
今天就到这里吧,大家看了,不要指望可以用它来写CSS,因为还有一些重要的概念没介绍。但光凭我们现在了解的东西,对于那些学过less的人来说,真是打击极大。显然,从易用性,功能等方面,已远胜less了。
to be continue...