文章目录
一. Sass 和 SCSS 有什么区别?
Sass 和 SCSS 其实是同一种东西,我们平时都称之为 Sass,两者之间不同之处有以下两点:
文件扩展名不同,Sass 是以“.sass”后缀为扩展名,而 SCSS 是以“.scss”后缀为扩展名
语法书写方式不同,Sass 是以严格的缩进式语法规则来书写,不带大括号({})和分号(; ),而 SCSS 的语法书写和我们的 CSS 语法书写方式非常类似。
Sass 语法:由于 Sass 是基于 Ruby 写出来,所以其延续了 Ruby 的书写规范。
$font-stack: Helvetica, sans-serif /*定义变量*/
$primary-color: #333 /*定义变量*/
body
font: 100% $font-stack
color: $primary-color
SCSS 语法:SCSS 和 CSS 写法无差别
$font-stack: Helvetica, sans-serif;
$primary-color: #333;
body {
font: 100% $font-stack;
color: $primary-color;
}
注意: “.sass”只能使用 Sass 老语法规则(缩进规则),“.scss”使用的是 Sass 的新语法规则。
二. 安装sass
1. mac系统
a. 安装Ruby,测试安装是否成功 ruby -v
b. 安装sass,命令gem install sass 或 sudo gem install sass
c. 安装compass,命令gem install compass
详细请看安装Sass | Sass中文网
2. window系统
1. 命令安装sass:同上
2. 本地安装 Sass
由于有时候直接使用上面的命令安装会让你无法正常实现安装(网络受限原因),当碰到这种情况之时,那么安装需要特殊去处理,可以通过下面的方法来实现 Sass 的正常安装:
可以到 Rubygems(http://rubygems.org/) 网站上将 Sass 的安装包(http://rubygems.org/gems/sass) 下载下来,然后在命令终端输入:
gem install <把下载的安装包拖到这里>
直接回车即可安装成功。
注意:在 iOSX 系统平台,可以直接将下载的安装包拖到 “gem install” 后面,如果在是 Windows 系统,需要手功输入安装的文件路径。
- 淘宝 RubyGems 镜像安装 Sass
除了下载 Sass 安装包到本地安装之外,碰到网络原因无法安装时还可以使用淘宝 RubyGems 镜像安装 Sass。只是我们需要通过 gem sources 命令来配置源,先移除默认的 https://rubygems.org 源,然后添加淘宝的源 https://ruby.taobao.org:
第一步:移动默认的源
gem sources --remove https://rubygems.org/
第二步:指定淘宝的源
gem sources -a https://ruby.taobao.org/
第三步:查看指定的源是不是淘宝源
gem sources -l
返回结果如下:
*** CURRENT SOURCES ***
https://ruby.taobao.org
请确保只有 ruby.taobao.org 。如果无误之后,执行下面的命令:
gem install sass
sass常用命令
gem update sass //更新sass
sass -v //查看sass版本
sass -h //查看sass帮助
三. 编译sass
1. 命令编译
//单文件转换命令
sass input.scss output.css
//单文件监听命令
sass --watch input.scss:output.css
//如果你有很多的sass文件的目录,你也可以告诉sass监听整个目录:
sass --watch app/sass:public/stylesheets
2. GUI工具编译
- Koala (http://www.w3cplus.com/preprocessor/sass-gui-tool-koala.html)
- CodeKit (http://www.w3cplus.com/preprocessor/sass-gui-tool-codekit.html
- ……
3. 自动化编译
- Grunt 配置 Sass 编译的示例代码
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
sass: {
dist: {
files: {
'style/style.css' : 'sass/style.scss'
}
}
},
watch: {
css: {
files: '**/*.scss',
tasks: ['sass']
}
}
});
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.registerTask('default',['watch']);
}
- Gulp 配置 Sass 编译的示例代码
var gulp = require('gulp');
var sass = require('gulp-sass');
gulp.task('sass', function () {
gulp.src('./scss/*.scss')
.pipe(sass())
.pipe(gulp.dest('./css'));
});
gulp.task('watch', function() {
gulp.watch('scss/*.scss', ['sass']);
});
gulp.task('default', ['sass','watch']);
4. 常见编译错误
最为常见的一个错误就是字符编译引起的。在Sass的编译的过程中,是不是支持“GBK”编码的。所以在创建 Sass 文件时,就需要将文件编码设置为“utf-8”。
另外一个错误就是路径中的中文字符引起的。建议在项目中文件命名或者文件目录命名不要使用中文字符。而至于人为失误造成的编译失败,在编译过程中都会有具体的说明,大家可以根据编译器提供的错误信息进行对应的修改。
5. 四种编译排版
//编译格式
sass --watch input.scss:output.css --style nested
//编译添加调试map
sass --watch input.scss:output.css --sourcemap
- 嵌套输出方式 nested
- 展开输出方式 expanded
- 紧凑输出方式 compact
- 压缩输出方式 compressed
详细请看安装Sass | Sass中文网
四. 变量
普通变量
定义后在全局范围内使用
$font-stack: Helvetica, sans-serif;
$primary-color: #333;
body {
font: 100% $font-stack;
color: $primary-color;
}
默认变量
在值后面加上 !default。
$baseLineHeight: 2; /*根据需求覆盖,在默认变量之前重新声明下变量即可。*/
$baseLineHeight: 1.5 !default;
body{
line-height: $baseLineHeight;
}
全局变量和局部变量
//SCSS
$color: orange !default;/*定义全局变量*/
.block {
color: $color;/*调用全局变量*/
}
em {
$color: red;/*定义局部变量(全局变量 $color 的影子)*/
a {
color: $color;/*调用局部变量*/
}
}
五. 嵌套
1. 选择器嵌套
nav {
ul {
margin: 0;
padding: 0;
list-style: none;
}
li { display: inline-block; }
}
2. 属性嵌套
Sass 中还提供属性嵌套,CSS 有一些属性前缀相同,只是后缀不一样,比如:border-top/border-right,与这个类似的还有 margin、padding、font 等属性。假设你的样式中用到了:
/*css*/
.box {
border-top: 1px solid red;
border-bottom: 1px solid green;
}
/*scss*/
.box {
border: {
top: 1px solid red;
bottom: 1px solid green;
}
}
3. 伪类嵌套 / 复合选择器 &
伪类嵌套:
a {
&:hover { text-decoration: underline; }
}
复合选择器:"&"必须出现在复合选择器开头的位置,后面再连接自定义的后缀,例如:
/*scss*/
#main {
color: black;
&-sidebar { border: 1px solid; }
}
/*css*/
#main {
color: black; }
#main-sidebar {
border: 1px solid; }
六. 引入 @import
局部文件导入
sass 局部文件 的文件名以 下划线开头。这样,sass就不会在编译时单独编译这个文件输出css,而只把这个文件用作导入。
/* _reset.scss*/
html, body, ul, ol {
margin: 0;
padding: 0;
}
/* base.scss*/
@import 'reset';
body {
font: 100% Helvetica, sans-serif;
background-color: #efefef;
}
嵌套导入
原生css导入
七. 混合 @mixin
1. 不带参数的混合
@mixin border-radius{
-webkit-border-radius: 5px;
border-radius: 5px;
}
2. 带参数的混合
不带值的参数
@mixin border-radius($radius){
-webkit-border-radius: $radius;
border-radius: $radius;
}
在调用的时候传一个参数值:
.box {
@include border-radius(3px);
}
带值的参数
@mixin border-radius($radius:5px){
-webkit-border-radius: $radius;
border-radius: $radius;
}
多个参数 用“…”代替
@mixin box-shadow($shadow...) { /*带有多个参数,使用“ … ”来替代*/
....
}
3. 复杂的混合
可以在大括号里面写上带有逻辑关系
@mixin box-shadow($shadow...) {
@if length($shadow) >= 1 {
@include prefixer(box-shadow, $shadow);
} @else{
$shadow:0 0 4px rgba(0,0,0,.3);
@include prefixer(box-shadow, $shadow);
}
}
4. 调用混合 @include
@mixin border-radius{
-webkit-border-radius: 3px;
border-radius: 3px;
}
button {
@include border-radius;
}
5. 混合的不足
生产冗余的代码块,相同的样式代码块没有合并在一起
/*scss*/
@mixin border-radius{
-webkit-border-radius: 3px;
border-radius: 3px;
}
.box {
@include border-radius;
margin-bottom: 5px;
}
.btn {
@include border-radius;
}
/*css*/
.box {
-webkit-border-radius: 3px;
border-radius: 3px;
margin-bottom: 5px;
}
.btn {
-webkit-border-radius: 3px;
border-radius: 3px;
}
八. 扩展/继承 @extend
//SCSS
.btn {
border: 1px solid #ccc;
padding: 6px 10px;
font-size: 14px;
}
.btn-primary {
background-color: #f36;
color: #fff;
@extend .btn;
}
占位符 %placeholder
通过 @extend 调用才会产生代码,没有被 @extend 调用就不产生任何代码块。
/*SCSS*/
%mt5 {
margin-top: 5px;
}
%pt5{
padding-top: 5px;
}
.btn {
@extend %mt5;
@extend %pt5;
}
九. 混合 vs 继承 vs 占位符
混合 | 继承 | 占位符 | |
---|---|---|---|
声明方式 | @mixin | .class | %placeholder |
调用方式 | @include | @extend | @extend |
使用环境 | 代码块涉及变量,需要传递不同的值 | 代码块不需要任何变量参数,而且有一个基类(使用继承会将调用相同基类的代码合并在一起) | 与继承相似。占位符是独立定义,不调用的时候是不会在 CSS 中产生任何代码 |
不足 | 不会自动合并相同的样式代码 | 如果基类不存在于HTML结构时,不管调用或不调用,编译的时候都产生基类的样式代码 | —— |
十. 插值 #{}
1. 当你想设置属性值的时候你可以使用字符串插入进来。
$properties: (margin, padding);
@mixin set-value($side, $value) {
@each $prop in $properties {
#{$prop}-#{$side}: $value;
}
}
.login-box {
@include set-value(top, 14px);
}
得到css:
.login-box {
margin-top: 14px;
padding-top: 14px;
}
2. 另一个有用的用法是构建一个选择器。
@mixin generate-sizes($class, $small, $medium, $big) {
.#{$class}-small { font-size: $small; }
.#{$class}-medium { font-size: $medium; }
.#{$class}-big { font-size: $big; }
}
@include generate-sizes("header-text", 12px, 20px, 40px);
得到css:
.header-text-small { font-size: 12px; }
.header-text-medium { font-size: 20px; }
.header-text-big { font-size: 40px; }
3. 注意
a. 如果用来生成代码或者生成另一个 mixins。第一个限制,这可能会很删除用于 Sass 变量的插值。
$margin-big: 40px;
$margin-medium: 20px;
$margin-small: 12px;
@mixin set-value($size) {
margin-top: $margin-#{$size};
}
.login-box {
@include set-value(big);
}
报错: error style.scss (Line 5: Undefined variable: “$margin-".)
b. #{}语法并不是随处可用,你也不能在 mixin 中调用。
@mixin updated-status {
margin-top: 20px;
background: #F00;
}
$flag: "status";
.navigation {
@include updated-#{$flag};
}
报错: error style.scss (Line 7: Invalid CSS after “…nclude updated-”: expected “}”, was “#{$flag};”)
4. 可以使用 @extend 中使用插值
%updated-status {
margin-top: 20px;
background: #F00;
}
.selected-status {
font-weight: bold;
}
$flag: "status";
.navigation {
@extend %updated-#{$flag};
@extend .selected-#{$flag};
}
可以动态的插入 .class 和 %placeholder,得到css:
.navigation {
margin-top: 20px;
background: #F00;
}
.selected-status, .navigation {
font-weight: bold;
}
十一. 注释
在 Sass 中注释有两种方式
- 类似 CSS 的注释方式,使用 ”/* ”开头,结属使用 ”*/ ”
- 类似 JavaScript 的注释方式,使用“//”
两者区别,前者会在编译出来的 CSS 显示,后者在编译出来的 CSS 中不会显示。
//定义一个占位符
%mt5 {
margin-top: 5px;
}
/*调用一个占位符*/
.box {
@extend %mt5;
}
得到css:
.box {
margin-top: 5px;
}
/*调用一个占位符*/
十二. 值列表
值列表 (lists) 是指 Sass 如何处理 CSS 中通过空格或者逗号分隔的一系列的值。
margin: 10px 15px 0 0
或者:
font-face: Helvetica, Arial, sans-serif
独立的值也被视为值列表——只包含一个值的值列表。
Sass列表函数(Sass list functions)赋予了值列表更多功能(Sass进级会有讲解):
- nth函数(nth function) 可以直接访问值列表中的某一项;
- join函数(join function) 可以将多个值列表连结在一起;
- append函数(append function) 可以在值列表中添加值;
- @each规则(@each rule) 则能够给值列表中的每个项目添加样式。
值列表中可以再包含值列表,比如 1px 2px, 5px 6px 是包含 1px 2px 与 5px 6px 两个值列表的值列表。如果内外两层值列表使用相同的分隔方式,要用圆括号包裹内层,所以也可以写成 (1px 2px) (5px 6px)。
当值列表被编译为 CSS 时,Sass 不会添加任何圆括号,因为 CSS 不允许这样做。(1px 2px) (5px 6px)与 1px 2px 5px 6px 在编译后的 CSS 文件中是一样的,但是它们在 Sass 文件中却有不同的意义,前者是包含两个值列表的值列表,而后者是包含四个值的值列表。
可以用 () 表示空的列表,这样不可以直接编译成 CSS,比如编译 font-family: ()时,Sass 将会报错。如果值列表中包含空的值列表或空值,编译时将清除空值,比如 1px 2px () 3px 或 1px 2px null 3px。
十三. 运算
1. 加法
ps:css中能做运算的,calc()函数 CSS calc() 函数
加法运算是 Sass 中运算中的一种,在变量或属性中都可以做加法运算。如:
.box {
width: 20px + 8in; /*编译后 width: 788px;*/
}
但对于携带不同类型的单位时,在 Sass 中计算会报错,如下例所示:
.box {
width: 20px + 1em; /* 报错:“Incompatible units: 'em' and ‘px'.” */
}
2. 减法
$full-width: 960px;
$sidebar-width: 200px;
.content {
width: $full-width - $sidebar-width;
}
同样的,运算时碰到不同类型的单位时,编译也会报错,如:
$full-width: 960px;
.content {
width: $full-width - 1em; /* 报错“Incompatible units: 'em' and ‘px’.” */
}
3. 乘法
Sass 中的乘法运算和前面介绍的加法与减法运算还略有不同。虽然他也能够支持多种单位(比如 em ,px , %),但当一个单位同时声明两个值时会有问题。比如下面的示例:
.box {
width:10px * 2px; /* 报错“20px*px isn't a valid CSS value.” */
}
如果两个值单位相同时,只需要为一个数值提供单位即可。上面的示例可以修改成:
.box {
width: 10px * 2; /* 编译后 width: 20px; */
}
同样的,运算时碰到不同类型的单位时,编译也会报错。
4. 除法
除法运算时,直接使用“/”符号做为除号时,将不会生效,编译时既得不到我们需要的效果,也不会报错。
.box {
width: 100px / 2; /* 编译后width: 100px / 2; */
}
修正这个问题,只需要给运算的外面 添加一个小括号( ) 即可:
.box {
width: (100px / 2); /* 编译后width: 50px; */
}
如果“/”符号在已有的数学表达式中时,也会被认作除法符号。如下面示例:
.box {
width: 100px / 2 + 2in; /* 编译后width: 242px;*/
}
另外,在 Sass 除法运算中,当用变量进行除法运算时,“/”符号也会自动被识别成除法,如下例所示:
$width: 1000px;
$nums: 10;
.item {
width: $width / 10; /* 编译后width: 100px;*/
}
.list {
width: $width / $nums; /* 编译后width: 100px;*/
}
综合上述,”/ ”符号被当作除法运算符时有以下几种情况:
- 如果数值或它的任意部分是存储在一个变量中或是函数的返回值。
- 如果数值被圆括号包围。
- 如果数值是另一个数学表达式的一部分。
如下所示:
//SCSS
p {
font: 10px/8px; /* 纯 CSS,不是除法运算*/
$width: 1000px;
width: $width/2; /* 使用了变量,是除法运算*/
width: round(1.5)/2; /* 使用了函数,是除法运算*/
height: (500px/2); /* 使用了圆括号,是除法运算*/
margin-left: 5px + 8px/2px; /* 使用了加(+)号,是除法运算*/
}
得到css:
p {
font: 10px/8px;
width: 500px;
height: 250px;
margin-left: 9px;
}
在除法运算时,如果两个值带有相同的单位值时,除法运算后会得到一个不带单位的数值。如下所示:
.box {
width: (1000px / 100px);
}
得到css:
.box {
width: 10;
}
5. 颜色运算
所有算数运算都支持颜色值,并且是分段运算的。也就是说,红、绿和蓝各颜色分段单独进行运算。如:
p {
color: #010203 + #040506;
}
计算公式为 01 + 04 = 05、02 + 05 = 07 和 03 + 06 = 09, 并且被合成为:
如此编译出来的 CSS 为:
p {
color: #050709;
}
算数运算也能将数字和颜色值 一起运算,同样也是分段运算的。如:
p {
color: #010203 * 2;
}
计算公式为 01 * 2 = 02、02 * 2 = 04 和 03 * 2 = 06, 并且被合成为:
p {
color: #020406;
}
6.字符运算
在 Sass 中可以通过加法符号“+”来对字符串进行连接。例如:
$content: "Hello" + "" + "Sass!";
.box:before {
content: " #{$content} ";
}
编译出来的CSS:
.box:before {
content: " Hello Sass! ";
}
除了在变量中做字符连接运算之外,还可以直接通过 +,把字符连接在一起:
div {
cursor: e + -resize;
}
编译出来的CSS:
div {
cursor: e-resize;
}
注意:
如果带引号的字符串在 + 符号左侧, 结果会是一个有引号的字符串。
如果没有引号的字符串在 + 符号左侧, 结果是一个没有引号的字符串。
p:before {
content: "Foo " + Bar;
font-family: sans- + "serif";
}
编译出来的 CSS:
p:before {
content: "Foo Bar";
font-family: sans-serif; }
sass函数请看:
Module: Sass::Script::Functions
Method List