用过CSS3的都知道,CSS3没有变量,也不支持任何逻辑脚本。人总是很聪明的,随着需求的增加,Sass诞生,目的在于使样式支持逻辑脚本,使程序猿们更高效的写样式,Sass脚本经过编译后,最终会转换成.css文件。Sass脚本有两种格式,分别是.sass和.scss,这两种格式的区别在于:.sass不使用大括号和分号。由于.scss的写法与.css更加相似,所以通常我们都使用.scss格式。本篇博客将从Sass安装、Sass编译到Sass语法应用逐步带程序猿们快速掌握Sass。
因为sass依赖于ruby环境,所以装sass之前先确认装了ruby,安装ruby的作用在于:它可以安装和更新sass。ruby官网下载地址:http://rubyinstaller.org/downloads/
在安装的时候,请勾选Add Ruby executables to your PATH这个选项,添加环境变量,这样在安装成功后就可以直接使用命令行使用ruby。安装完成后需测试安装有没有成功,可运行CMD输入命令:
$ ruby -v
如能正确显示ruby版本号,表明安装成功。由于国内对外网有所限制,接着需要安装gem源的淘宝镜像,目的在于保证顺利下载Sass等资源。运行CMD输入命令:
//1.删除原gem源 $ gem sources --remove https://rubygems.org/ //2.添加国内淘宝源 $ gem sources -a https://ruby.taobao.org/ //3.打印是否替换成功 $ gem sources -l //4.更换成功后打印如下 *** CURRENT SOURCES *** https://ruby.taobao.org/
如果您系统不支持https,请将淘宝源更换成:gem sources -a http://gems.ruby-china.org。至此,所有准备工作就绪,开始安装Sass,安装命令行如下:
安装成功后,同样可通过sass -v检测是否安装成功,若能显示版本号则表示安装成功。
$ gem install sass $ gem install compass
$ sass input.scss output.css
如需实现动态编译(只要.scss改变就会马上编译成.css文件),编译命令如下:
$ sass --watch input.scss:output.css
如果是多文件编译,编译对象也可以是文件目录:
$ sass --watch app/sass:public/stylesheets
编辑出来的文件有四种排版可配置,分别是nested、expanded、compact和compressed。以expanded为例,配置时只需在命令行末尾加入--style expanded即可。
$ sass --watch input.scss:output.css --style expanded
这四种排版的区别程序猿们可以编译后自己对比一下,或直接去官网查看,在实际开发过程中,较常用的是expanded和compressed排版。当然,如果对命令行没有操作习惯,还可以使用编译工具koala,官网下载地址:http://koala-app.com/index-zh.html.
——技巧——
(1)在.scss开头加上@charset "utf-8";这样编译时遇到中文便不会出错;
(2)命名变量时常用到横杆或下横岗,如$link-color和$link_color,在编译时这两者并没有区别,指向的是同一对象。
1.变量
变量用$符号定义,如$fontSize: 20px;变量的好处在于一次定义多次使用,免去重复写相同的代码。变量的格式分为普通变量、默认变量、特殊变量、多值变量和对象变量。
(1)普通变量,最简单的变量使用方法。
-
@charset
"utf-8";
-
-
//编译前.scss
-
$fontSize:
20px;
-
div {
-
font-size: $fontSize;
-
}
-
-
//编译后.css
-
div {
-
font-size:
20px;
-
}
(2)默认变量,在普通变量后加上!default,目的在于强调变量用意,可修改,常用于组件的入参定义。
-
//编译前.scss
-
$fontSize:
20px !
default;
-
div {
-
font-size: $fontSize;
-
}
-
-
//编译后.css
-
div {
-
font-size:
20px;
-
}
(3)特殊变量,通过 #{变量名称} 的方式,可引用为样式名称。
-
//编译前.scss
-
$direction: top !
default;
-
div {
-
border-#{$direction}:
1px solid red;
-
}
-
-
//编译后.css
-
div {
-
border-top:
1px solid red;
-
}
(4)多值变量,该种变量可赋多个值,值之间用空格隔开,引用时通过nth(多值变量,索引);的方式获取值内容,索引从1开始计数。
-
//编译前.scss
-
$linkColor: red blue;
-
div {
-
cursor: pointer;
-
color: nth($linkColor,
1);
-
//此处&表示this,即自身div。
-
&:hover {
-
color: nth($linkColor,
2);
-
}
-
}
-
-
//编译后.css
-
div {
-
cursor: pointer;
-
color: red;
-
}
-
div:hover {
-
color: blue;
-
}
(5)对象变量,指用(key1:value1, key2:value2)的形式定义变量。通过map-get($map,$key)获取内容值,除此之外,还有map-merge($map1,$map2), map-keys($map), map-values($map)等方法。
-
//编译前.scss
-
$mapColor:(
"color1":red,
"color2":blue);
-
div{
-
cursor: pointer;
-
color: map-get($mapColor,
"color1");
-
&:hover {
-
color: map-get($mapColor,
"color2");
-
}
-
}
-
-
//编译后.css
-
div {
-
cursor: pointer;
-
color: red;
-
}
-
div:hover {
-
color: blue;
-
}
2.嵌套
(1)选择器嵌套,最常用的嵌套语法,是指当描述多层级元素样式时,子层级元素可嵌套到父层级元素内,这种语法极大地优化了样式代码的可读性。
-
//编译前.scss
-
ul {
-
list-style: none;
-
li {
-
float: left;
-
a {
-
color: red;
-
&:hover {
-
color: yellow;
-
}
-
}
-
}
-
}
-
-
//编译后.css
-
ul {
-
list-style: none;
-
}
-
ul li {
-
float: left;
-
}
-
ul li a {
-
color: red;
-
}
-
ul li a:hover {
-
color: yellow;
-
}
(2)群组嵌套,是指嵌套元素时每次可嵌套多个元素,嵌套的元素用逗号隔开。
-
//编译前.scss
-
.container {
-
h1, h2, h3 {margin-bottom:
.8em}
-
}
-
nav,aside {
-
a {
-
color: blue
-
}
-
}
-
-
//编译后.css
-
.container h1, .container h2, .container h3 {
-
margin-bottom:
.8em;
-
}
-
-
nav a, aside a {
-
color: blue;
-
}
(3)属性嵌套,主要用于具有类似相同属性名称的元素嵌套,注意与其它嵌套写法的差别,在嵌套时大挂弧前会多一个冒号,由于这种嵌套方法不利于可读性,建议尽量少用。
-
//编译前.scss
-
div {
-
border: {
-
style: solid;
-
left: {
-
color: red;
-
}
-
right: {
-
color: yellow;
-
}
-
}
-
}
-
-
//编译后.css
-
div {
-
border-style: solid;
-
border-left-color: red;
-
border-right-color: yellow;
-
}
(4)样式嵌套,是指样式与样式间的嵌套,注意样式嵌套时带空格与不带空格的区别:即子级与同级的区别。
-
//编译前.scss
-
.list {
-
border: solid
1px red;
-
&.item {
-
border: solid
1px yellow;
-
}
-
& .item {
-
border: solid
1px yellow;
-
}
-
}
-
-
//编译后.css
-
.list {
-
border: solid
1px red;
-
}
-
.list.item {
-
border: solid
1px yellow;
-
}
-
.list .item {
-
border: solid
1px yellow;
-
}
(5)跳出嵌套@at-root,用于定义有相同开头的系列样式,但又不在嵌套内。
-
//编译前.scss
-
.block {
-
color: red;
-
@at-root #{&}__element {
-
color: yellow;
-
}
-
@at-root #{&}__modifier {
-
color: orange;
-
}
-
}
-
-
//编译后.css
-
.block {
-
color: red;
-
}
-
.block__element {
-
color: yellow;
-
}
-
.block__modifier {
-
color: orange;
-
}
3.导入
在开发大型项目时,往往会有一些公共样式文件,该类文件可以通过@import实现导入。公共样式文件命名规则是用下横杠_,如_common.scss,导入时无需写后缀名和下横杠,导入可用如下语句:@import "common";
-
//编译前.scss
-
@mixin block{
-
color: red;
-
}
-
-
.demo{
-
@include block;
-
}
-
-
//编译后.css
-
.demo {
-
color: red;
-
}
上例中,.demo通过包含的方式,将@mixin定义的block对象样式引入到了自身。要注意的是,有这样一种情况,在.demo中再次定义color属性(注意,block对象中的color:red脚本是一定会加入到.demo中),那么具体是取@mixin定义的block对象样式还是.demo自己定义的color,取决于自身color和@include引入之间的脚本顺序。@mixin还可以实现带参,用法如下 :
-
//编译前.scss
-
@mixin param($opa){
-
opacity: $opa;
-
}
-
.opa{
-
@include param(
0.5);
-
}
-
-
//编译后.css
-
.opa {
-
opacity:
0.5;
-
}
配合@content用法,可以用来解决css3的@media等带来的问题。它可以使 @mixin接受一整块样式,接受的样式从@content开始,用法如下:
-
//编译前.scss
-
@mixin max-screen($res) {
-
@media only screen and ( max-width: $res) {
-
@content;
-
}
-
}
-
-
@include max-screen(
480px) {
-
body {
-
color: red
-
}
-
}
-
-
//编译后.css
-
@media only screen and (max-width:
480px) {
-
body {
-
color: red;
-
}
-
}
-
//编译前.scss
-
.h {
-
border:
4px solid #ff9aa9;
-
}
-
-
.speaker {
-
@extend .h;
-
border-width:
2px;
-
}
-
-
//编译后.css
-
.h, .speaker {
-
border:
4px solid #ff9aa9;
-
}
-
-
.speaker {
-
border-width:
2px;
-
}
此时.h的样式会被编译出来。如不想把父结构样式编译出来,可使用占位符继承,在父结构命名前加上百分号%
-
//编译前.scss
-
%h {
-
border:
4px solid #ff9aa9;
-
}
-
-
.speaker {
-
@extend %h;
-
border-width:
2px;
-
}
-
-
//编译后.css
-
.speaker {
-
border:
4px solid #ff9aa9;
-
}
-
-
.speaker {
-
border-width:
2px;
-
}
(注)mixin与继承实现的目的是一样的,都是为了共享样式,只是写法不同。但在实际应用中,尽可能使用mixin来实现共享样式,据官网表示,接下来的Sass版本很可能会去掉继承的语法。
-
//编译前.scss
-
$baseFontSize:
16px !
default;
-
@
function pxToRem($px) {
-
@
return $px / $baseFontSize *
1rem;
-
}
-
-
.test1 {
-
font-size: $baseFontSize;
-
}
-
-
.test2 {
-
font-size: pxToRem(
16px);
-
}
-
-
//编译后.css
-
.test1 {
-
font-size:
16px;
-
}
-
-
.test2 {
-
font-size:
1rem;
-
}
-
//编译前.scss
-
$num1:
10px !
default;
-
$num2:
5px !
default;
-
$num3:
10 !
default;
-
$num4:
5 !
default;
-
.jia{
-
font-size: $num1 + $num2;
-
}
-
-
.jian{
-
font-size: $num1 - $num2;
-
}
-
-
.cheng{
-
font-size: ($num3 * $num4)+px;
-
}
-
.chu{
-
font-size: ($num3 / $num4)+px;
-
}
-
-
//编译后.css
-
.jia {
-
font-size:
15px;
-
}
-
-
.jian {
-
font-size:
5px;
-
}
-
-
.cheng {
-
font-size:
50px;
-
}
-
-
.chu {
-
font-size:
2px;
-
}
(注)运算乘除时需先把单位拿出来,否则会编译失败。
8.条件判断
条件判断有@if @else和三目判断两种,@if @else用法如下:
-
//编译前.scss
-
$show:
true;
-
$type: car;
-
-
.test1 {
-
@
if $show {
-
opacity:
1;
-
}
-
@
else {
-
opacity:
0;
-
}
-
}
-
-
.test2 {
-
@
if $type==bus {
-
color: yellow;
-
}
-
@
else
if $type==car {
-
color: red;
-
}
-
@
else {
-
color: blue;
-
}
-
}
-
-
//编译后.css
-
.test1 {
-
opacity:
1;
-
}
-
-
.test2 {
-
color: red;
-
}
三目判断用法如下:
-
//编译前.scss
-
.test3 {
-
font-size:
if(
false,
1px,
2px);
-
}
-
-
//编译后.css
-
.test3 {
-
font-size:
2px;
-
}
9.循环
循环主要使用的关键字有@for和@each。先来介绍@for,这种循环并不常用,因为这种循环并不支持入参,只简单实现1、2、3...这样的排序循环,主要语法有from+through和form+to,区别在于to并不包括最后的边界值。如
-
//编译前.scss
-
@
for $i
from
1 through
3 {
-
.through-#{$i} {
-
width:
2em * $i;
-
}
-
}
-
-
@
for $i
from
1 to
3 {
-
.to-#{$i} {
-
width:
2em * $i;
-
}
-
}
-
-
//编译后.css
-
.through
-1 {
-
width:
2em;
-
}
-
-
.through
-2 {
-
width:
4em;
-
}
-
-
.through
-3 {
-
width:
6em;
-
}
-
-
.to
-1 {
-
width:
2em;
-
}
-
-
.to
-2 {
-
width:
4em;
-
}
@each循环则较为常用,它的入参可以是一维数组、二维数组或map对象格式。
-
//一维数组
-
$arr: a, b, c;
-
//二维数组
-
$arrs: (a1, b1, c1),(a2, b2, c2);
-
//map对象格式
-
$map: (key1: value1,
key2: value2);
一维数组用法:
-
//编译前.scss
-
$animal-list: puma,sea-slug,egret,salamander;
-
@each $animal
in $animal-list {
-
.#{$animal}-icon {
-
background-image: url(
'/images/#{$animal}.png');
-
}
-
}
-
-
//编译后.css
-
.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");
-
}
二维数组用法:
-
//编译前.scss
-
$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
-
.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对象格式用法:
-
//编译前.scss
-
$headings: (h1:
2em,
h2:
1.5em,
h3:
1.2em);
-
@each $header,$size
in $headings {
-
#{$header} {
-
font-size: $size;
-
}
-
}
-
-
//编译后.css
-
h1 {
-
font-size:
2em;
-
}
-
-
h2 {
-
font-size:
1.5em;
-
}
-
-
h3 {
-
font-size:
1.2em;
-
}
至此,本篇博客有关Sass的知识已经介绍完毕,现在有没有发现Sass并没有想象中那么困难,开始您的Sass编程之路吧,让我们一起来高效编写CSS脚本。