Sass 學(xué)習(xí)筆記

本文以 sass 語(yǔ)法點(diǎn)為主線展開(kāi),但語(yǔ)法細(xì)節(jié)不在此贅述,如有疑問(wèn)請(qǐng)移駕至 http://sass-lang.com 自行查閱。我所認(rèn)為的 sass 的優(yōu)勢(shì):結(jié)構(gòu)化(層級(jí)關(guān)系更清晰)、組件化(公用模塊的提取)、繼承(公用樣式的提?。Mx者能在瀏覽完此文后有所體會(huì)。

進(jìn)入正文前,先為大家推薦一枚神奇的網(wǎng)站:https://www.sassmeister.com/。

一、變量

變量默認(rèn)值

變量默認(rèn)值的價(jià)值在于進(jìn)行組件化開(kāi)發(fā)。

應(yīng)用場(chǎng)景

一個(gè)站點(diǎn)內(nèi)的公用模塊在不同頁(yè)面的展現(xiàn)形式會(huì)有些許不同,例如一個(gè)列表模塊中列表項(xiàng)的分隔方式在不同頁(yè)面存在差異。

傳統(tǒng)做法:

/* m-module-list.css */
.module-list li {
    font-size: 14px;
    line-height: 22px;
    color: #666;
    padding: 15px;
    background-color: #FFF;
    border-bottom: 1px solid #F0F0F0;
    margin-bottom: none;
}

/* style.css */
@import 'm-module-list.css';

.module-list li {
    border-bottom: none;
    margin-bottom: 10px;
}

顯然,傳統(tǒng)做法會(huì)產(chǎn)生 冗余 代碼。對(duì) .module-list li 的 border-bottom 及 margin-bottom 定義了兩次(很好的體現(xiàn)了 css 層疊 的理念)。

使用變量默認(rèn)值:

/* m-module-list.scss */
$borderBottom: 1px solid #F0F0F0 !default;
$marginBottom: none !default;

.module-list {
    li {
        font-size: 14px;
        line-height: 22px;
        color: #666;
        padding: 15px;
        background-color: #FFF;
        border-bottom: $borderBottom;
        margin-bottom: $marginBottom;
    }
}

/* style.scss */
$borderBottom: none;
$marginBottom: 10px;

@import 'm-module-list';

解析后的 css 代碼:

.module-list li {
    font-size: 14px;
    line-height: 22px;
    color: #666;
    padding: 15px;
    background-color: #FFF;
    border-bottom: none;
    margin-bottom: 10px;
}

上述方法是存在缺陷的:定義 全局變量 很容易造成 污染 。但自 sass v3.4 便不存在這樣的問(wèn)題了,為什么這樣講?

先看一段示例:

$color: red;
p {
    $color: yellow;
    color: $color;
}
a {
    color: $color;
}

sass v3.3 解析后的 css 代碼:

p {
    color: yellow;
}
a {
    color: yellow;
}

sass v3.4 解析后的 css 代碼:

p {
    color: yellow;
}
a {
    color: red;
}

自 sass v3.4 變量的解析遵循:底層作用域內(nèi)聲明的變量相當(dāng)于局部變量,不影響全局變量。

使用 javascript 解釋:

var a = 1; 
(function () { 
    var a = 5; 
})(); 
console.log(a); // -> 1

而 sass v3.3 及以前對(duì)變量的設(shè)計(jì)思路為:在底層作用域聲明變量相當(dāng)于修改全局變量,它處調(diào)用該變量時(shí)會(huì)使用覆蓋的新值。

使用 javascript 解釋:

var a = 1; 
(function () { 
    a = 5; 
})(); 
console.log(a); // -> 5

特殊變量

  • 應(yīng)用于選擇器

  • 應(yīng)用于屬性

特殊變量的應(yīng)用十分廣泛,在此不做特別介紹。請(qǐng)自行留意文中 #{$var} 這樣的書(shū)寫(xiě)方式,那就是所謂的特殊變量。

多值變量

  • List 類型
應(yīng)用場(chǎng)景

由于存在圖片失效或尺寸不合規(guī)定的情況,我們通常需要為圖片添加默認(rèn)底色及占位。例如浮動(dòng)布局中元素尺寸的變化會(huì)擾亂呈現(xiàn)效果:

當(dāng)然,上述問(wèn)題可以通過(guò)為左側(cè)元素清除浮動(dòng)或延時(shí)加載圖片等方法解決。在此,我們僅講述為圖片添加占位這一方法,效果如下:

在不同的業(yè)務(wù)場(chǎng)景下,占位圖風(fēng)格各異。例如我司的常規(guī)需求、活動(dòng)類需求、專題類需求所啟用的占位圖就在顏色及底紋上存在差異。

我們可以定義 3 種圖片類型 default、activity、special 存儲(chǔ)在 List 類型變量 $thumbType 中,這樣書(shū)寫(xiě)語(yǔ)義清晰、利于拓展、精簡(jiǎn)代碼。

相關(guān)代碼:

$thumbType: default, activity, special;
@each $type in $thumbType {
    %#{$type}-thumb {
        background: url("../img/#{$type}-nothumb.jpg") no-repeat 0 0;
        background-size: 100% auto;
        padding-bottom: 100%;
        height: 0;
        overflow: hidden;
    }
}

.section1 .thumb {
    @extend %default-thumb;
}
.section2 .thumb {
    @extend %activity-thumb;
}
.section3 .thumb {
    @extend %special-thumb;
}

解析后的 css 代碼:

.section1 .thumb {
    background: url("../img/default-nothumb.jpg") no-repeat 0 0;
    background-size: 100% auto;
    padding-bottom: 100%;
    height: 0;
    overflow: hidden;
}
.section2 .thumb {
    background: url("../img/activity-nothumb.jpg") no-repeat 0 0;
    background-size: 100% auto;
    padding-bottom: 100%;
    height: 0;
    overflow: hidden;
}
.section3 .thumb {
    background: url("../img/special-nothumb.jpg") no-repeat 0 0;
    background-size: 100% auto;
    padding-bottom: 100%;
    height: 0;
    overflow: hidden;
}
  • Map 類型
應(yīng)用場(chǎng)景

通常,一個(gè)站點(diǎn)含多套配色方案,以按鈕的配色為例:主色、輔助色、弱色。每套配色又由多種狀態(tài)色組成:常態(tài)色、點(diǎn)擊色、失效色。

我們可以將這些色值按照一定的規(guī)則儲(chǔ)存在 Map 類型變量 中,這樣做的優(yōu)勢(shì)為:

  • 結(jié)構(gòu)及語(yǔ)義清晰,增強(qiáng)了可讀性且易于修改。

  • 添加新的配色方案相當(dāng)于添加配置項(xiàng),無(wú)需撰寫(xiě)大量代碼。

相關(guān)代碼:

$btnColor: (
    main: (
        normal: (
            font: #C53336,
            border: #C53336,
            background: #FFF
        ),
        active: (
            font: #FFF,
            border: #C53336,
            background: #C53336
        ),
        disabled: (
            font: #999,
            border: #F5F5F5,
            background: #F5F5F5
        )
    ),
    weak: (
        normal: (
            font: #333,
            border: #666,
            background: #FFF
        ),
        active: (
            font: #FFF,
            border: #666,
            background: #666
        ),
        disabled: (
            font: #999,
            border: #CCC,
            background: #FFF
        )
    )
);
@mixin btnColor ($font, $border, $background) {
    color: $font;
    border-color: $border;
    background-color: $background;
}
@each $type, $status in $btnColor {
    %btn-#{$type} {
        $normal: map-get($status, normal);
        $active: map-get($status, active);
        $disabled: map-get($status, disabled);
        
        @include btnColor(map-values($normal)...);
        
        &:active {
            @include btnColor(map-values($active)...);
        }
        &.disabled {
            @include btnColor(map-values($disabled)...);
        }
    }
}

a.btn-main {
    @extend %btn-main;
}
a.btn-weak {
    @extend %btn-weak;
}

解析后的 css 代碼:

a.btn-main {
    color: #C53336;
    border-color: #C53336;
    background-color: #FFF;
}
a.btn-main:active {
    color: #FFF;
    border-color: #C53336;
    background-color: #C53336;
}
a.disabled.btn-main {
    color: #999;
    border-color: #F5F5F5;
    background-color: #F5F5F5;
}
a.btn-weak {
    color: #333;
    border-color: #666;
    background-color: #FFF;
}
a.btn-weak:active {
    color: #FFF;
    border-color: #666;
    background-color: #666;
}
a.disabled.btn-weak {
    color: #999;
    border-color: #CCC;
    background-color: #FFF;
}

二、嵌套

嵌套可增強(qiáng)文件的結(jié)構(gòu)性及可讀性,但嵌套層級(jí)過(guò)多卻是大忌,@at-root 可解決該問(wèn)題。

@at-root

@at-root 可防止選擇器的優(yōu)先級(jí)過(guò)高。

先看一段很糟糕的代碼,嵌套層級(jí)過(guò)多。層級(jí)關(guān)系的展現(xiàn)雖清晰,卻莫名加高了選擇器的 優(yōu)先級(jí) 。那么在重置樣式的時(shí)候便需要加更高的優(yōu)先級(jí),由此惡性循環(huán)。

.parent {
    .child1 {
        width: 20px;
        .child1-1 {
            width: 20px; 
            .child1-1-1 {
                width: 20px;
            }
        }
    }
}

解析后的 css 代碼:

.parent .child1 {
    width: 20px;
}
.parent .child1 .child1-1 {
    width: 20px;
}
.parent .child1 .child1-1 .child1-1-1 {
    width: 20px;
}

顯然,.parent .child1 .child1-1 .child1-1-1 的優(yōu)先級(jí)很高卻完全沒(méi)必要,我們需要做的便是降級(jí)。

.parent {
    .child1 {
        width: 20px;
        @at-root .child1-1 {
            width: 20px;
            @at-root .child1-1-1 {
                width: 20px;
            }
        }
    }
}

解析后的 css 代碼:

.parent .child1 {
    width: 20px;
}
.child1-1 {
    width: 20px;
}
.child1-1-1 {
    width: 20px;
}

其實(shí)這并不是我想要的,我想要的是:

.parent .child1 {
    width: 20px;
}
.parent .child1-1 {
    width: 20px;
}
.parent .child1-1-1 {
    width: 20px;
}

顯然 @at-root 無(wú)法控制跳出的級(jí)數(shù),無(wú)奈。

@at-root 的另一應(yīng)用場(chǎng)景便是 @keyframes。動(dòng)畫(huà)的專屬性較強(qiáng),嵌套的寫(xiě)法能清晰的標(biāo)明其被應(yīng)用之處。在做功能刪除時(shí)只需直接干掉一整段代碼,無(wú)需查找對(duì)應(yīng)的 @keyframes 順便思考其影響范圍,省時(shí)高效。

示例代碼:

.demo {
    animation: motion 1s infinite;
    @at-root {
        @keyframes motion {
            0% {background-color: red;}
            100% {background-color: yellow;}
        }
    }
}

解析后的 css 代碼:

.demo {
    animation: motion 1s infinite;
}
@keyframes motion {
    0% {background-color: red;}
    100% {background-color: yellow;}
}

其實(shí)上述是 sass v3.3 之前的做法,自 sass v3.4 這樣書(shū)寫(xiě)即可:

.demo {
    animation: motion 1s infinite;
    @keyframes motion {
        0% {background-color: red;}
        100% {background-color: yellow;}
    }
}

@keyframes 會(huì)自動(dòng)跳出父級(jí)的限制。


三、繼承

@mixin + @include

可傳遞參數(shù),可設(shè)置參數(shù)默認(rèn)值。

應(yīng)用場(chǎng)景

相信大家都很反感在使用 transition、transform 這類 css3 屬性時(shí)需要巴拉巴拉添加一堆前綴。

有了 sass 我們便可以定義一個(gè)自動(dòng)添加前綴的方法啦!引用時(shí),只需傳入屬性名及屬性值,非常方便。且欲添加新的所須兼容的瀏覽器時(shí),只需在 $compatibleBrowser 中添加配置項(xiàng)。若是使用傳統(tǒng)做法,想象下某天老板要我們兼容 ms 了,你是要把全站代碼修改一遍?

相關(guān)代碼:

$compatibleBrowser: webkit, moz, o;
@mixin addPrefix ($property, $value) {
    @each $prefix in $compatibleBrowser {
        -#{$prefix}-#{$property}: $value;
    }
    #{$property}: $value;
}
.demo {
    background-color: red;
    @include addPrefix(transition, background-color 2s);
    &:hover {
        background-color: yellow;
    }
}

解析后的 css 代碼:

.demo {
    background-color: red;
    -webkit-transition: background-color 2s;
    -moz-transition: background-color 2s;
    -o-transition: background-color 2s;
    transition: background-color 2s;
}
.demo:hover {
    background-color: yellow;
}

% + @extend

用于定義通用樣式最為合適。

應(yīng)用場(chǎng)景

通常,我們會(huì)創(chuàng)建這樣一個(gè)文件 common.css 來(lái)定義一些通用樣式,引用時(shí)在對(duì)應(yīng)元素的 html 標(biāo)簽上添加相應(yīng)的 class 即可。

而 sass 的做法如下:

%horizontal-scroll {
    white-space: nowrap;
    overflow-x: scroll;
    li {
        display: inline-block;
        vertical-align: middle;
    }
    &::-webkit-scrollbar {
        width: 0;
        height: 0;
        opacity: 0;
    }
}

section.horizontal-scroll {
    @extend %horizontal-scroll;
}

解析后的 css 代碼:

section.horizontal-scroll {
    white-space: nowrap;
    overflow-x: scroll;
}
section.horizontal-scroll li {
    display: inline-block;
    vertical-align: middle;
}
section.horizontal-scroll::-webkit-scrollbar {
    width: 0;
    height: 0;
    opacity: 0;
}

這樣做的優(yōu)勢(shì)為:

  • css 樣式與 html 結(jié)構(gòu)解耦。

  • 去除冗余 css 代碼。

第一條優(yōu)勢(shì)顯而易見(jiàn),下面來(lái)為大家解釋第二條:在代碼被壓縮上線時(shí),傳統(tǒng)做法會(huì)使得未被引用的通用樣式一同被上線,而 sass 在被解析為 css 時(shí)會(huì)去除由 % 定義的未被引用的通用樣式。


四、函數(shù)

產(chǎn)生值,非行為。

不要與 javascript 中的函數(shù)混淆。調(diào)用時(shí)并非執(zhí)行了某段操作,而是返回了經(jīng)過(guò)某些操作后產(chǎn)生的值,其實(shí)類似于有 return 值的 javascript 函數(shù)。


五、語(yǔ)句

三目判斷

書(shū)寫(xiě)形式:

  • if(條件, 條件為真所取值, 條件為假所取值)

莫名覺(jué)得會(huì)很常用,與 javascript 中的 ? : 作用相同。

@if

應(yīng)用場(chǎng)景

定義多行省略時(shí)(以 3 行為例),變更顯示行數(shù)只需修改 line-clamp 屬性值,代碼如下:

.ellipsis-row3 {
    overflow: hidden;
    display: -webkit-box;
    text-overflow: -o-ellipsis-lastline;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
}

而定義單行省略只需如下 3 行:

.ellipsis-row1 {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

兩段代碼差異較大,而我們又想將多行與單行的情況融合在一個(gè)通用樣式內(nèi)。此時(shí),可以使用 if 語(yǔ)句將單行省略單獨(dú)定義。

相關(guān)代碼:

@for $lineCount from 1 through 3 {
    %ellipsis-row#{$lineCount} {
        overflow: hidden;
        @if $lineCount == 1 {
            white-space: nowrap;
            text-overflow: ellipsis;
        } @else {
            display: -webkit-box;
            text-overflow: -o-ellipsis-lastline;
            -webkit-box-orient: vertical;
            -webkit-line-clamp: $lineCount;
        }
    }
}

.section1 p {
    @extend %ellipsis-row1;
}
.section2 p {
    @extend %ellipsis-row2;
}
.section3 p {
    @extend %ellipsis-row3;
}

解析后的 css 代碼:

.section1 p {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}
.section2 p {
    overflow: hidden;
    display: -webkit-box;
    text-overflow: -o-ellipsis-lastline;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
}
.section3 p {
    overflow: hidden;
    display: -webkit-box;
    text-overflow: -o-ellipsis-lastline;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
}

@for

for 循環(huán)的書(shū)寫(xiě)形式有兩種:

  • @for $var from start through end

  • @for $var from start to end

第一種在循環(huán)遍歷時(shí)會(huì)對(duì)第 end 項(xiàng)進(jìn)行操作,第二種則不會(huì)。本人認(rèn)為習(xí)慣使用一種即可,不然易混淆。

應(yīng)用場(chǎng)景

我司喜好做 “固定模板” 需求:運(yùn)營(yíng)同學(xué)會(huì)將一張圖片裁切成 n 個(gè)區(qū)域,點(diǎn)擊每一區(qū)域的行為有所不同。比如一張美女的面部圖,點(diǎn)擊其眼睛時(shí)會(huì)推薦一些雙眼皮項(xiàng)目,點(diǎn)擊其鼻子時(shí)會(huì)推薦一些鼻綜合項(xiàng)目等等(我司是做微整形交易平臺(tái)的)。

區(qū)域劃分是有一定規(guī)則的,如下圖:當(dāng)前行僅含一張圖片時(shí)圖片寬度為 100%,兩張時(shí)為 50%,... n 張時(shí)為 (100 / n)%。

相關(guān)代碼:

%clear-float {
    &:after {
        content: "";
        display: block;
        height: 0;
        clear: both;
        visibility: hidden;
    }
}
%adapt-image {
    display: block;
    width: 100%;
}
%static-template {
    div {
        @extend %clear-float;
        a {
            float: left;           
            img {
                @extend %adapt-image;
            }
        }
    }
    @for $itemCount from 1 through 3 {
        .count#{$itemCount} {
            a {
                width: 100%/$itemCount;
            }
        }
    }
}
section.static-template {
    @extend %static-template;
}

解析后的 css 代碼:

section.static-template div:after {
    content: "";
    display: block;
    height: 0;
    clear: both;
    visibility: hidden;
}
section.static-template div a img {
    display: block;
    width: 100%;
}
section.static-template div a {
    float: left;
}
section.static-template .count1 a {
    width: 100%;
}
section.static-template .count2 a {
    width: 50%;
}
section.static-template .count3 a {
    width: 33.33333333%;
}

上述其實(shí)是 多列布局 的一個(gè)實(shí)例,多列布局的應(yīng)用很廣泛,比如導(dǎo)航欄:

@each

each 可循環(huán)遍歷兩種數(shù)據(jù)類型:

  • @each $var in list

  • @each $var in map

具體實(shí)例請(qǐng)向上翻至 多值變量 。


2017/11/06 續(xù)更

Sass 安裝

Sass 依賴于 Ruby 環(huán)境,若未安裝 Ruby 請(qǐng)移駕此處下載。安裝過(guò)程請(qǐng)勾選 Add Ruby executables to your PATH 確保添加環(huán)境變量。

若你具備翻墻技能請(qǐng)直接:

gem install sass

下面介紹如何不翻墻安裝 Sass:

配置 gem sources

# 移除 https://rubygems.org/
gem sources --remove https://rubygems.org/

# 添加 https://gems.ruby-china.org/
gem sources -a https://gems.ruby-china.org/

# 查看 sources 確保僅有 https://gems.ruby-china.org/
gem sources -l

下載 sass.gem

下載地址

安裝 sass.gem

gem install [sass.gem 路徑]/sass.gem

作者:呆戀小喵

相關(guān)文章:通過(guò) sass-resources-loader 全局注冊(cè) Sass 變量

我的后花園:https://sunmengyuan.github.io/garden/

我的 github:https://github.com/sunmengyuan

原文鏈接:https://sunmengyuan.github.io/garden/2017/05/17/sass-application.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容