世界上最成熟、最穩定、最強大的專業級 CSS 擴展語言! - Sass 官網css
主要內容:html
我本地結合 gulp+sass 自動化工具使用,主要以下:前端
npm install node-sass gulp-sass --save-dev
複製代碼
gulpfile.js
文件主要配置以下,詳情能夠參考這裏。node
const { src, dest, watch } = require("gulp");
const sass = require("gulp-sass");
sass.compiler = require("node-sass");
function scss() {
return src(scssGlobSrc)
.pipe(sass({ outputStyle: "expanded" }).on("error", sass.logError))
.pipe(dest("dist/sass"));
}
exports.scss = scss;
複製代碼
啓動:gulp scss
。git
/*未編譯樣式*/
.box {
width: 300px;
height: 400px;
&-title {
height: 30px;
line-height: 30px;
}
}
複製代碼
nested 編譯排版格式github
/*命令行內容*/
sass style.scss:style.css --style nested
/*編譯事後樣式*/
.box {
width: 300px;
height: 400px;
}
.box-title {
height: 30px;
line-height: 30px;
}
複製代碼
expanded 編譯排版格式shell
/*命令行內容*/
sass style.scss:style.css --style expanded
/*編譯事後樣式*/
.box {
width: 300px;
height: 400px;
}
.box-title {
height: 30px;
line-height: 30px;
}
複製代碼
compact 編譯排版格式npm
/*命令行內容*/
sass style.scss:style.css --style compact
/*編譯事後樣式*/
.box {
width: 300px;
height: 400px;
}
.box-title {
height: 30px;
line-height: 30px;
}
複製代碼
compressed 編譯排版格式gulp
/*命令行內容*/
sass style.scss:style.css --style compressed
/*編譯事後樣式*/
.box {
width: 300px;
height: 400px;
}
.box-title {
height: 30px;
line-height: 30px;
}
複製代碼
body {
// 這種註釋內容不會出如今生成的css文件中
color: #333;
/* 這種註釋內容會出如今生成的css文件中 */
padding: 0;
}
複製代碼
body {
color: #333;
/* 這種註釋內容會出如今生成的css文件中 */
padding: 0;
}
複製代碼
很是簡單明瞭,變量申明:$color: #4a4a4a;
,變量引用:color: $color;
,具體例子演示以下:bootstrap
$bg-color: #f90;
$font-color: #444;
body {
background: $bg-color;
color: $font-color;
}
.selected {
border: 1px solid $font-color;
}
複製代碼
body {
background: #f90;
color: #444;
}
.selected {
border: 1px solid #444;
}
複製代碼
文檔:在 Sass 中,你能夠像俄羅斯套娃那樣在規則塊中嵌套規則塊。sass 在輸出 css 時會幫你把這些嵌套規則處理好,避免你的重複書寫。
看個例子,基本就知道什麼意思:
ul {
li {
a {
color: $font-color;
&:hover {
color: red;
}
&::after {
content: "...";
}
}
}
}
複製代碼
ul li a {
color: #444;
}
ul li a:hover {
color: red;
}
ul li a::after {
content: "...";
}
複製代碼
夠簡潔,不過有一些嵌套規則,須要稍稍留意,好比:
&
>、+ 和 ~
父選擇器的標識符&
,記住&
是爸爸,你能夠在爸爸的後邊,也能夠在爸爸的前邊,隨你,哈哈哈哈:
nav a {
color: $font-color;
/* Dad after */
&:hover {
color: red;
}
/* Dad before */
.header & {
color: #000;
}
}
複製代碼
nav a {
color: #444;
}
/* Dad after */
nav a:hover {
color: red;
}
/* Dad before */
.header nav a {
color: #000;
}
複製代碼
Dad 是爸爸們:nav a
,什麼場景能用到Dad before
?想一想nav a
是通用樣式,我想給 header 組件單獨nav a
的樣式,即.header nav a
,即.header &
。
固然,還能夠這樣用:
.main {
color: black;
&-sidebar {
border: 1px solid;
}
}
// css
.main {
color: black;
}
.main-sidebar {
border: 1px solid;
}
複製代碼
文檔例子:
.container {
h1,
h2,
h3 {
margin-bottom: 0.8em;
}
}
nav,
aside {
a {
color: blue;
}
}
複製代碼
.container h1,
.container h2,
.container h3 {
margin-bottom: 0.8em;
}
nav a,
aside a {
color: blue;
}
複製代碼
名字就已經告訴我們這個規則的要點是:羣組。大括號{
前端的均可以是一個羣組,好比.container
,好比nav, aside
,不論多少。
作爲羣組的任何一員,有權利獲取子嗣,並且還得跟其餘羣組成員如出一轍,若 Ta 有 三個(h1, h2, h3
)子嗣,那羣組的任何一員也得各自有三個子嗣;Ta 若是隻有一個(a
)子嗣,即便羣組人不少,也得每一個成員一人一個。
演練:有三個組件header article footer
,我但願字體顏色有默認值,連接例外,而且有 hover 變化。
.header,
.acticle,
.footer {
color: $font-color;
a {
color: #999;
&:hover {
color: red;
}
}
}
複製代碼
.header,
.acticle,
.footer {
color: #444;
}
.header a,
.acticle a,
.footer a {
color: #999;
}
.header a:hover,
.acticle a:hover,
.footer a:hover {
color: red;
}
複製代碼
子組合選擇器 >
和同層組合選擇器 +、~
,和 CSS 的規則一致。
/* 選擇article 後的同層全部 article 元素 */
article ~ article {
border-top: 1px dashed #ccc;
}
/* 選擇nav元素後緊跟的article元素 */
nav + article {
margin-top: 0;
}
/* 選擇article下的全部命中section選擇器的元素 */
article > section {
background: #eee;
}
複製代碼
文檔例子:
article {
~ article {
border-top: 1px dashed #ccc;
}
> section {
background: #eee;
}
dl > {
dt {
color: #333;
}
dd {
color: #555;
}
}
nav + & {
margin-top: 0;
}
}
複製代碼
article ~ article {
border-top: 1px dashed #ccc;
}
article > section {
background: #eee;
}
article dl > dt {
color: #333;
}
article dl > dd {
color: #555;
}
nav + article {
margin-top: 0;
}
複製代碼
規則:把屬性名從中劃線-的地方斷開,在根屬性後邊添加一個冒號
:
,緊跟一個{ }
塊,把子屬性部分寫在這個{ }
塊中。就像 css 選擇器嵌套同樣,sass 會把你的子屬性一一解開,把根屬性和子屬性部分經過中劃線-
鏈接起來,最後生成的效果與你手動一遍遍寫的 css 樣式同樣:
nav {
border: {
style: solid;
width: 1px;
color: #ccc;
}
}
nav {
border: 1px solid #ccc {
left: 0px;
}
}
// css
nav {
border-style: solid;
border-width: 1px;
border-color: #ccc;
}
nav {
border: 1px solid #ccc;
border-left: 0px;
}
複製代碼
一句話:我要把border-style
裏的-
打斷,拆散左右,並替換成:
,從新使用{}
嵌套使用,宗旨就是不破不立,有破纔有立,把全部重複的東西通通歸併,只寫關鍵部位。
在單獨使用 css 的 @import
規則導入文件,是不及 link
的效率,好比加載字體庫,有次在項目中就吃過這個虧,那會發誓打死我也不用這個規則。
sass 的@import
規則是在生成 css 文件時就把相關文件導入進來,因此,和 css 的@import
沒有什麼關係,放心食用。
可是因爲 sass 兼容原生的 css,因此它也支持原生的 CSS@import
,好比導入文件或者 url 是以 .css
結尾的。
使用:
// 經常使用方法
@import "header";
@import "footer";
// 多個導入
@import "rounded-corners", "text-shadow";
// 嵌套導入
.blue-theme {
@import "blue-theme";
}
複製代碼
若是將文件命名爲 _colors.scss
,便不會編譯_colours.css
文件,可是導入時依然是@import "colors";
。
Sass 中 @media 指令與 CSS 中用法同樣,不過還容許其在 CSS 規則中嵌套,編譯時,@media 將被編譯到文件的最外層,包含嵌套的父選擇器。
.sidebar {
width: 300px;
@media screen and (orientation: landscape) {
width: 500px;
}
}
/* 拼接 and */
@media screen {
.sidebar {
@media (max-width: 1140px) {
width: 960px;
}
}
.other {
@media (max-width: 640px) {
width: 100%;
}
}
}
複製代碼
.sidebar {
width: 300px;
}
@media screen and (orientation: landscape) {
.sidebar {
width: 500px;
}
}
/* 拼接 and */
@media screen and (max-width: 1140px) {
.sidebar {
width: 960px;
}
}
@media screen and (max-width: 640px) {
.other {
width: 100%;
}
}
複製代碼
和其餘語言同樣,就是繼承。好比代碼中的.error
,以及同級.intrusion
,都會被繼承:
.error {
border: 1px #f00;
background-color: #fdd;
}
.error.intrusion {
background-image: url("/image/hacked.png");
}
.seriousError {
@extend .error;
border-width: 3px;
}
複製代碼
.error,
.seriousError {
border: 1px #f00;
background-color: #fdd;
}
.error.intrusion,
.intrusion.seriousError {
background-image: url("/image/hacked.png");
}
.seriousError {
border-width: 3px;
}
複製代碼
和 JavaScript 的 if 同樣:
$type: monster;
p {
@if $type == ocean {
color: blue;
} @else if $type == monster {
color: green;
} @else {
color: black;
}
}
複製代碼
p {
color: green;
}
複製代碼
區別在於 through 與 to 的含義:through 包含最後一位,而 to 不包含:
@for $i from 1 to 3 {
.list-#{$i} {
width: 1em * $i;
}
}
@for $i from 1 through 3 {
.item-#{$i} {
width: 2rem * $i;
}
}
複製代碼
.list-1 {
width: 1em;
}
.list-2 {
width: 2em;
}
.item-1 {
width: 2rem;
}
.item-2 {
width: 4rem;
}
.item-3 {
width: 6rem;
}
複製代碼
相似於 JavaScript 的 for...in
:
@each $kind in small, middle, large {
.#{$kind}-icon {
background-image: url("/images/#{$kind}-icon.png");
}
}
複製代碼
.small-icon {
background-image: url("/images/small-icon.png");
}
.middle-icon {
background-image: url("/images/middle-icon.png");
}
.large-icon {
background-image: url("/images/large-icon.png");
}
複製代碼
混合器使用@mixin
標識符定義,經過@include
來使用這個混合器,用來解決大段重用的代碼。
@mixin clearfix {
display: inline-block;
&:after {
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
* html & {
height: 1px;
}
}
.clearfix {
@include clearfix;
}
複製代碼
.clearfix {
display: inline-block;
}
.clearfix:after {
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
* html .clearfix {
height: 1px;
}
複製代碼
最強大的一點就是如同函數通常,能夠傳參,不只能夠指定默認值,而且可使用關鍵詞參數,這樣就不用管參數先後順序了:
@mixin border-value($width: 1px, $color: #333, $style: solid) {
border-width: $width;
border-color: $color;
border-style: $style;
}
/*不傳參*/
h1 {
@include border-value;
}
/*傳參*/
h2 {
@include border-value(2px, #666, dashed);
}
/*關鍵詞傳參*/
h3 {
@include border-value($style: dashed, $width: 3px, $color: #999);
}
複製代碼
/*不傳參*/
h1 {
border-width: 1px;
border-color: #333;
border-style: solid;
}
/*傳參*/
h2 {
border-width: 2px;
border-color: #666;
border-style: dashed;
}
/*關鍵詞傳參*/
h3 {
border-width: 3px;
border-color: #999;
border-style: dashed;
}
複製代碼
與 mixin 相同,也能夠傳遞若干個全局變量給函數做爲參數。一個函數能夠含有多條語句,須要調用 @return
輸出結果。
$grid-width: 40px;
$gutter-width: 10px;
@function grid-width($n) {
@return $n * $grid-width + ($n - 1) * $gutter-width;
}
.sidebar1 {
width: grid-width(5);
}
.sidebar2 {
width: grid-width($n: 10);
}
複製代碼
.sidebar1 {
width: 240px;
}
.sidebar2 {
width: 490px;
}
複製代碼
SassScript 支持 6 種主要的數據類型:
1, 2, 13, 10px
"foo", 'bar', baz
blue, #04a3f9, rgba(255,0,0,0.5)
true, false
null
1.5em 1em 0 2em, Helvetica, Arial, sans-serif
(key1: value1, key2: value2)
SassScript 支持數字的加減乘除、取整等運算 (+, -, *, /, %)
,關係運算 <, >, <=, >=
也可用於數字運算,相等運算 ==
, !=
可用於全部數據類型。
經過 #{}
插值語句能夠在選擇器或屬性名中使用變量,避免 Sass 運行運算表達式。
入口文件 bootstrap.scss
的引入組件不少,咱們就挑一個看看,好比下面是咱們最終的 float 內容:
.float-left {
float: left !important;
}
.float-right {
float: right !important;
}
.float-none {
float: none !important;
}
@media (min-width: 576px) {
.float-sm-left {
float: left !important;
}
.float-sm-right {
float: right !important;
}
.float-sm-none {
float: none !important;
}
}
@media (min-width: 768px) {
.float-md-left {
float: left !important;
}
.float-md-right {
float: right !important;
}
.float-md-none {
float: none !important;
}
}
@media (min-width: 992px) {
.float-lg-left {
float: left !important;
}
.float-lg-right {
float: right !important;
}
.float-lg-none {
float: none !important;
}
}
@media (min-width: 1200px) {
.float-xl-left {
float: left !important;
}
.float-xl-right {
float: right !important;
}
.float-xl-none {
float: none !important;
}
}
複製代碼
而後,咱們去看看 bootstrap 是如何實現的:
根據 bootstrap.scss
裏的內容@import "mixins";
,進入當前目錄下的_mixins.scss
,看到@import "mixins/float";
,因此繼續打開mixins
目錄下的 _float.scss
。
_float.scss
全部內容以下:
// stylelint-disable declaration-no-important
@each $breakpoint in map-keys($grid-breakpoints) {
@include media-breakpoint-up($breakpoint) {
$infix: breakpoint-infix($breakpoint, $grid-breakpoints);
.float#{$infix}-left {
float: left !important;
}
.float#{$infix}-right {
float: right !important;
}
.float#{$infix}-none {
float: none !important;
}
}
}
複製代碼
接着,有三個地方,我不知道是什麼,如map-keys()
,media-breakpoint-up()
,breakpoint-infix()
。
map-keys()
返回 map 裏面全部的 key:$grid-breakpoints: (
xs: 0,
sm: 576px,
md: 768px,
lg: 992px,
xl: 1200px
) !default;
@each $breakpoint in map-keys($grid-breakpoints) {
.#{$breakpoint} {
color: red;
}
}
// css
.xs {
color: red;
}
.sm {
color: red;
}
.md {
color: red;
}
.lg {
color: red;
}
.xl {
color: red;
}
複製代碼
資料:Sass map 詳解
media-breakpoint-up()
,自定義函數,主要是根據媒體查詢給出不一樣的結果// Media of at least the minimum breakpoint width. No query for the smallest breakpoint.
// Makes the @content apply to the given breakpoint and wider.
@mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints) {
$min: breakpoint-min($name, $breakpoints);
@if $min {
@media (min-width: $min) {
@content;
}
} @else {
@content;
}
}
複製代碼
這裏breakpoint-min()
也是個函數:
// Minimum breakpoint width. Null for the smallest (first) breakpoint.
//
// >> breakpoint-min(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))
// 576px
@function breakpoint-min($name, $breakpoints: $grid-breakpoints) {
$min: map-get($breakpoints, $name);
@return if($min != 0, $min, null);
}
複製代碼
這裏的map-get
同 map-keys
用法,返回 map 裏面指定能夠的 value
:
$min-num: breakpoint-min(sm, $grid-breakpoints);
@media (min-width: $min-num) {
p {
color: #444;
}
}
// css
@media (min-width: 576px) {
p {
color: #444;
}
}
複製代碼
@content
用在mixin
裏面的,當定義一個mixin
後,而且設置了@content
以後,、@include
的時候能夠傳入相應的內容到mixin
裏面:
$color: white;
@mixin colors($color: blue) {
background-color: $color;
@content;
border-color: $color;
}
.colors {
@include colors {
color: $color;
}
}
// css
.colors {
background-color: blue;
color: white;
border-color: blue;
}
複製代碼
breakpoint-infix()
,自定義函數:// Returns a blank string if smallest breakpoint, otherwise returns the name with a dash in front.
// Useful for making responsive utilities.
//
// >> breakpoint-infix(xs, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))
// "" (Returns a blank string)
// >> breakpoint-infix(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))
// "-sm"
@function breakpoint-infix($name, $breakpoints: $grid-breakpoints) {
@return if(breakpoint-min($name, $breakpoints) == null, "", "-#{$name}");
}
複製代碼
根據註釋咱們演示一下:
$min-value-sm: breakpoint-infix(sm, $grid-breakpoints);
$min-value-xs: breakpoint-infix(xs, $grid-breakpoints);
.float#{$min-value-sm}-left {
float: left;
}
.float#{$min-value-xs}-left {
float: left;
}
// css
.float-sm-left {
float: left;
}
.float-left {
float: left;
}
複製代碼
最後,咱們把全部關於 float 的內容組合在一塊兒:
$grid-breakpoints: (
xs: 0,
sm: 576px,
md: 768px,
lg: 992px,
xl: 1200px
) !default;
@function breakpoint-min($name, $breakpoints: $grid-breakpoints) {
$min: map-get($breakpoints, $name);
@return if($min != 0, $min, null);
}
@function breakpoint-infix($name, $breakpoints: $grid-breakpoints) {
@return if(breakpoint-min($name, $breakpoints) == null, "", "-#{$name}");
}
@mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints) {
$min: breakpoint-min($name, $breakpoints);
@if $min {
@media (min-width: $min) {
@content;
}
} @else {
@content;
}
}
@each $breakpoint in map-keys($grid-breakpoints) {
@include media-breakpoint-up($breakpoint) {
$infix: breakpoint-infix($breakpoint, $grid-breakpoints);
.float#{$infix}-left {
float: left !important;
}
.float#{$infix}-right {
float: right !important;
}
.float#{$infix}-none {
float: none !important;
}
}
}
複製代碼
這樣直接就能夠在環境裏跑起來了。