SASS入门与实践
前言
SASS是最古老,也是最成熟的CSS預處理語言,誕生于2007年。有著比LESS更強大的功能。不過最開始的縮進式語法,并不能被廣大用戶接受,所以雖然出現很早但是普及卻不如LESS,但是隨著自身語法的改進和Ruby on Rails的大力推進,絕大多數人都開始選用SASS作為自己的預處理器開發利器。官網給出的介紹是:它是一門高于CSS的元語言,能用來編寫清晰且結構化的描述文件樣式,有著比普通CSS更強大的功能。提供更簡潔、更優雅的語法,同時提供多種功能來創建可維護和管理的樣式表。
什么是CSS預處理器
CSS 預處理器用一種專門的編程語言,為 CSS 增加了一些編程的特性,進行 Web 頁面樣式設計,然后再編譯成正常的 CSS 文件,以供項目使用,特點是預處理器是一門單獨的語言,有變量、邏輯判斷、函數,還有,使用時,需要編譯成正常的CSS
CSS預處理器技術已經非常成熟,當然有許多不同的CSS預處理器,比如SASS/LESS/Stylus 等等,關于那種預處理器是最優秀的,各大技術論壇爭論紛紛。本文將要介紹的就是能夠讓絕大多數前端開發工程師滿意的一種:SASS
SASS 和 SCSS
兩者其實是同一種東西,我們平時都稱之為Sass,兩者不同之處有以下兩點
-
文件擴展名不同分別為.sass和.scss
-
語法書寫方式不同。SASS以嚴格縮進式語法來編寫,不包含大括號和分號,類似Jade;而SCSS的語法書寫則和CSS的語法書寫非常類似,舉個栗子
SASS語法$font-stack: Helvetica, sans-serif //定義變量$primary-color: #333 //定義變量bodyfont: 100% $font-stackcolor: $primary-colorSCSS語法$font-stack: Helvetica, sans-serif;$primary-color: #333;body {font: 100% $font-stack;color: $primary-color;}兩者編譯出來的CSS文件body {font: 100% Helvetica, sans-serif;color: #333;} 復制代碼
可見,Sass和CSS的書寫語法差別很大,而Sass書寫則和CSS幾乎一樣,所以這也是為什么越來越多的前端開發使用Sass中的SCSS方式來開發的原因
Sass的安裝
MAC系統
- brew install ruby
- sudo gem install sass
- sass -v
Window系統
- 去官網下載Ruby安裝包
打開ruby 命令行
命令行輸入 gem install sass 復制代碼如果上面安裝失敗,可能是因為該安裝途徑已經被墻了,需要更換安裝的源,這里我們使用淘寶的源,附上安裝步驟
Sass基礎
接下來所說的所有語法書寫格式都是以.scss格式
基本格式
以.scss作為文件后綴,代碼在一組大括號內且結束處都有一個分號作為結尾,同樣的CSS代碼
body {font: 100% Helvetica, sans-serif;color: #333; } 復制代碼我們使用SCSS語法格式將上面重寫一下
$font-stack: Helvetica, sans-serif; $primary-color: #333;body {font: 100% $font-stack;color: $primary-color; } 復制代碼編譯.scss文件
Sass是一個預處理器,將編寫的.scss文件編譯成對應的.css文件,項目中使用的還是.css為后綴的文件。具體的編譯方式有三種:命令編譯、GUI編譯、自動化編譯
-
命令編譯:使用指令代碼進行編譯
sass src/:out/
如 sass sass/:css/ 這條指令意味著把’sass’文件夾中的所有’.scss’文件編譯成’.css’文件,并把這些’.css’文件放置到css目錄下。這樣做的缺點是只能一次性編譯,每次更改后都需要重復編譯。
如果這樣做太麻煩的話,可以使用’watch’功能,watch功能會監視指定文件的改動,自動執行編譯
sass --watch src/:out/ 復制代碼-
GUI編譯:
推薦使用Koloa
-
自動化編譯:這里推薦使用 gulp
var gulp = require('gulp');var sass = require('gulp-ruby-sass');gulp.task('sass', function () {gulp.sass('./scss/*.scss').pipe(gulp.dest('./css'));});gulp.task('watch', function() {gulp.watch('scss/*.scss', ['sass']);});gulp.task('default', ['sass','watch']); 復制代碼 -
常見編譯問題
- Sass不支持‘GBK’編碼,所以在創建文件時就需要將編碼格式設置為’utf-8’
- 不建議在項目中的文件路徑或者文件名中出現中文漢字
不同的輸出風格
Sass中編譯出來的樣式風格可以按照不同的風格進行顯示。主要包括如下幾種
- 嵌套式輸出 nested
- 展開式輸出 expanded
- 緊湊式輸出 compact
- 壓縮式輸出 compressed
具體的輸出方式通過編譯指令完成
sass --watch test.scss:test.css --style nested 復制代碼對于如下的css樣式,分別舉例四種輸出方式
nav {ul {margin: 0;}li { display: inline-block; }a {display: block;} } 復制代碼-
嵌套式輸出 nested
nav ul {margin: 0; }nav li {display: inline-block; }nav a {display: block;} 復制代碼 -
展開式輸出 expanded(和nested類似,但是大括號獨占一行)
nav ul {margin: 0; }nav li {display: inline-block; }nav a {display: block;} 復制代碼 -
緊湊型輸出 compact
nav ul { margin: 0; }nav li { display: inline-block; }nav a { display: block;} 復制代碼 -
壓縮性輸出 compressed
nav ul{margin:0;padding:0;}nav li{display:inline-block}nav a{display:block;} 復制代碼
SCSS 語法
變量
- 聲明變量
Sass中變量包含三部分:$、變量名稱、變量值,如
$width: 300px 復制代碼-
變量類型
-
普通變量
$fontSize: 12px;body{font-size: $fontSize; } 復制代碼 -
默認變量:僅需要在值得后面加上 !default
$baseLineHeight:1.5 !default;body{line-height: $baseLineHeight; } 復制代碼
-
類似于JavaScript中的短路賦值 var onePoint = req.query.from || ‘China’;
變量的調用
直接在需要賦值的地方使用$ 變量名就可以完成調用
作用域
分為全局作用域和局部作用域
$color: orange !default;//定義全局變量.block {color: $color;//調用全局變量,orange }em {$color: red;//定義局部變量a {color: $color;//調用局部變量,red} } 復制代碼混合宏
使用混合宏可以自定義重復利用的而組件,關鍵字是 @mixin。在混合宏中,我們可以自定義代碼的樣式,添加判斷邏輯等等
-
混合宏的聲明
不帶參數的混合宏
@mixin border-radius {-webkit-border-radius: 5px;border-radius: 5px;} 復制代碼帶參數的混合宏:入參如果不存在使用默認的5px。這個5px可以是頁面的默認屬性,而特殊的border-radius則可以在調用是通過入參控制
@mixin border-radius($radius:5px){-webkit-border-radius: $radius;border-radius: $radius;} 復制代碼 -
調用混合宏
調用不帶參數的混合宏(上文中定義的)
button {@include border-radius;} 復制代碼調用帶參數的混合宏
button {@include border-radius(3px);} 復制代碼
混合宏的不足
混合宏可以解決重復代碼塊的問題,但是也有不足。最大的不足之處在于混合宏會生成冗余的代碼塊,比如在不同的地方調用一個相同的混合宏時。
@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; } 復制代碼可以看出兩個地方調用混合宏,兩個地方都出現了混合宏的代碼內容,并沒有只能的將相同的代碼進行合并成如下的樣式。
.box .btn{-webkit-border-radius: 3px;border-radius: 3px; }.box {margin-bottom: 5px; } 復制代碼@extend 繼承
CSS原本就有繼承機制的,內部元素默認會繼承外部元素的某些屬性。Sass中也有繼承這么一說,通過@extend來繼承已經存在的代碼塊。
.btn {border: 1px solid #ccc;padding: 6px 10px;font-size: 14px; }.btn-primary {background-color: #f36;color: #fff;@extend .btn; }.btn-second {background-color: orange;color: #fff;@extend .btn; } 復制代碼編譯后
.btn, .btn-primary, .btn-second {border: 1px solid #ccc;padding: 6px 10px;font-size: 14px; }.btn-primary {background-color: #f36;color: #fff; }.btn-second {background-clor: orange;color: #fff; } 復制代碼從示例代碼中我們可以看出,在Sass中的繼承,可以繼承類樣式中的所有代碼,而編譯出的CSS會合并到一起,形成組合選擇器.btn, .btn-primary, .btn-second {}的形式
混合宏定義了一個可以支持參數傳遞的復用代碼塊,但是代碼塊本身必不能直接作為樣式;繼承作為雖然不能提供參數傳遞的復用代碼塊,但是父類本身可以作為樣式~
占位符
Sass中的占位符 %placeholder 類似于繼承中的基類,可以通過@extend繼承選中基類中的代碼。但是不同的是通過占位符聲明的代碼,如果不被@extend的話,不會產生任何代碼,所以和繼承是有差別的,舉個栗子。
%mt5 {margin-top: 5px; } %pt5{padding-top: 5px; }.btn {@extend %mt5;@extend %pt5; }.block {@extend %mt5;span {@extend %pt5;} } 復制代碼從輸出中可以看到,占位符的輸出中不包含占位符本身
.btn, .block {margin-top: 5px; }.btn, .block span {padding-top: 5px; } 復制代碼相同的實現,我們再來看一下繼承
.mt5 {margin-top: 5px; } .pt5{padding-top: 5px; }.btn {@extend .mt5;@extend .pt5; }.block {@extend .mt5;span {@extend .pt5;} }繼承的輸出中包含了基類本身 .mt5, .btn, .block {margin-top: 5px; }.pt5, .btn, .block span {padding-top: 5px; } 復制代碼是不是感覺占位符很像繼承和@mixin的混合體。不支持參數傳遞的復用代碼塊(繼承),本身不出現在輸出中(@mixin)
混合宏 VS 繼承 VS 占位符
什么時候該使用它們中的某一個呢?在這里總結一下如何使用這幾個容易讓人弄混的概念
- 混合宏:不會自動合并相同的樣式文件,會造成代碼冗余,但是可以傳遞參數
- 繼承:會合并相同的代碼,通過組合選擇器輸出,但是不能傳遞參數
- 占位符:編譯出來的代碼和使用繼承基本上是一樣的,自是不會在代碼中出現占位符本身
占位符是獨立定義的,不調用的時候是不會在代碼充產生任何代碼。而繼承首先要保證有一個基類的存在,不管調用與不調用,積累的樣式都會出現在編譯出來的額CSS代碼中
下面的代碼幫助大家記憶三者的區別
//========= //混合宏寫法 @mixin mt($var){margin-top: $var; } .block {@include mt(4px);span {display:block;@include mt(3px);} } .header {color: orange;@include mt(5px);span{display:block;@include mt(5px);} } //混合宏寫法輸出 .block { margin-top: 4px; } .block span { display: block; margin-top: 3px; } .header { color: orange; margin-top: 5px; } .header span { display: block; margin-top: 5px; }//========= //繼承寫法 .mt{margin-top: 5px; } .block {@extend .mt;span {display:block;@extend .mt;} } .header {color: orange;@extend .mt;span{display:block;@extend .mt;} }// 繼承寫法輸出 .mt, .block, .block span, .header, .header span { margin-top: 5px; } .block span { display: block; } .header { color: orange; } .header span { display: block; }//========= //占位符 %mt{margin-top: 5px; } .block {@extend %mt;span {display:block;@extend %mt;} } .header {color: orange;@extend %mt;span{display:block;@extend %mt;} } //占位符寫法輸出 .block, .block span, .header, .header span { margin-top: 5px; } .block span { display: block; } .header { color: orange; } .header span { display: block; } 復制代碼轉載于:https://juejin.im/post/5a31d22a51882510b2756325
總結
- 上一篇: 去电视视频广告再也不用购买vip去广告
- 下一篇: 家庭多路监控方案思路分析