隨著css工程化的普及尝哆,sass在前端工程中越來越舉足輕重淑蔚。當然sass并不局限于管理css全局變量、mixin之類的"臟活累活"蒋搜。
這篇文章會跟隨工程化前端一步一步記錄sass中那些不為人知抒倚,但是又非常使用的小技巧分享給大家褐着。
建議大家收藏隨時觀看。
內(nèi)置函數(shù)
sass官網(wǎng)提供了很多實用的內(nèi)置函數(shù)托呕,當然目前我也是在一步一步探索這些函數(shù)含蓉。目前我會將常用到的內(nèi)置函數(shù)以及場景分享給大家使用洋访。
darken內(nèi)置函數(shù)
定義
lighten()和darken()兩個函數(shù)都是圍繞顏色的亮度值做調(diào)整的,其中l(wèi)ighten()函數(shù)會讓顏色變得更亮谴餐,與之相反的darken()函數(shù)會讓顏色變得更暗姻政。這個亮度值可以是0~1之間。
lighten(#fff,10%) //原色的亮度值 增加百分之10亮度
draken(#fff,10%) // 在原色的基礎上 減少百分之10亮度
應用場景
lighten和darken這兩個內(nèi)置函數(shù)經(jīng)常被用到元素被hover/focus時岂嗓,當我們hover汁展,一個元素的時候。此時并不希望改變這個元素的色值厌殉,但是又想要用戶感知到鼠標停留在這個元素上食绿。此時這兩個內(nèi)置函數(shù)就發(fā)揮了他們的作用了。
@mixin button-type(
$background,
$border,
$color,
$hover-background: lighten($background, 7.5),
$hover-border: lighten($border, 10%),
$hover-color: $color
) {
color: $color;
background: $background;
border-color: $border;
&:hover {
color: $hover-color;
background: $hover-background;
border-color: $hover-border;
}
&:focus,
&.is-focus {
color: $hover-color;
background: $hover-background;
border-color: $hover-border;
}
&[disabled],
&.is-disabled {
color: $color;
background: $background;
border-color: $border;
}
}
desaturate
飽和度(Saturation)是指色彩的純度公罕,飽和度越高色彩越純越濃器紧,飽和度越低則色彩變灰變淡。
sass中的desaturate函數(shù)就是針對飽和度操作的內(nèi)置方法楼眷。
desaturate(amount) //=> color
使amount必須之間的數(shù)字0%和100%(包含)铲汪。
@warn
When writing mixins[1] and functions[2], you may want to discourage users from passing certain arguments or certain values. They may be passing legacy arguments that are now deprecated, or they may be calling your API in a way that’s not quite optimal.
編寫MixIn和函數(shù)時,您可能希望勸阻用戶傳遞某些參數(shù)或某些值罐柳。他們可能正在傳遞現(xiàn)在已棄用的傳統(tǒng)參數(shù)掌腰,或者他們可能會以不太最佳的方式調(diào)用您的API。
簡單來說在mixin或者function內(nèi)部张吉,我們可以通過@warn操作符給用戶提示一些警告內(nèi)容輸出在控制臺齿梁。
@mixin prefix($property, $value, $prefixes) {
@each $prefix in $prefixes {
@if not index($known-prefixes, $prefix) {
@warn "Unknown prefix #{$prefix}.";
}
-#{$prefix}-#{$property}: $value;
}
#{$property}: $value;
}
控制臺會提示
Warning: Unknown prefix wekbit.
example.scss 6:7 prefix()
example.scss 16:3 root stylesheet
Inspect()斷電函數(shù)
其實Inspect()函數(shù)用的比較少,主要是用來做校驗類型的肮蛹。
Inspect(...)表達式中的內(nèi)容如果是正常會返回對應的內(nèi)容勺择,如果發(fā)生錯誤則會彈出一個錯誤提示。
Map相關內(nèi)容
Map-has-key
If map contains a value associated with $key.
$font-weights: ("regular": 400, "medium": 500, "bold": 700);
map.has-key($font-weights, "regular"); // true
map.has-key($font-weights, "bolder"); // false
map.has-key()在scss中的條件判斷時應用場景特別多伦忠。
比如下方這段代碼
$--sm: 768px !default;
$--md: 992px !default;
$--lg: 1200px !default;
$--xl: 1920px !default;
$--breakpoints: (
'xs' : (max-width: $--sm - 1),
'sm' : (min-width: $--sm),
'md' : (min-width: $--md),
'lg' : (min-width: $--lg),
'xl' : (min-width: $--xl)
);
@mixin res($key, $map: $--breakpoints) {
// 循環(huán)斷點Map省核,如果存在則返回
@if map.has-key($map, $key) {
@media only screen and #{inspect(map-get($map, $key))} {
@content;
}
} @else {
@warn "Undefeined points: `#{$map}`";
}
}
map.get(map,k1,k2,...)
簡單來說就是通過key在map中取到對應的value
config, a, b, c); // d
占位符選擇器%作用
定義
Sass 額外提供了一種特殊類型的選擇器:占位符選擇器 (placeholder selector)。與常用的 id 與 class 選擇器寫法相似缓苛,只是 # 或 . 替換成了 %芳撒。
比如:
%heading {
margin-top: 0; // 1
margin-bottom: $headings-margin-bottom;
font-family: $headings-font-family;
font-style: $headings-font-style;
font-weight: $headings-font-weight;
line-height: $headings-line-height;
color: $headings-color;
}
應用場景
其實使用%在大多數(shù)(所有)場景下邓深,我的理解就是和@mixin是一樣的效果未桥。使用%占位符選擇器的樣式,只能被@extend進行調(diào)用芥备。
需要注意的是冬耿,如果使用占位符選擇器%定義的樣式圣猎,單獨使用的時候(未通過extend)進行調(diào)用掀潮,那么這段樣式是不會編譯到css的輸出結果之后的逮诲。
Partials import
定義
和css類似scss支持@import命令,但css的import命令每次調(diào)用都會創(chuàng)建一個額外的html請求易茬,但scss的import命令是編譯時將文件包含在css中,不需要額外發(fā)起請求寞忿。
如果我們需要導入 SCSS 或者 Sass 文件交胚,但又不希望將其編譯為 CSS,只需要在文件名前添加下劃線绊起,這樣會告訴 Sass 不要單獨編譯這些文件精拟,但導入語句中卻不需要添加下劃線。
簡單來說虱歪,項目目錄中的所有scss文件在編譯階段都會被編譯成為一個個css文件蜂绎。
但是對于一個公用樣式文件,此時我們并不需要將它編譯成為單獨的css文件笋鄙,而是希望將公用文件中的樣式插入到對應引入樣式文件中师枣,我們只需要在引入它的文件中將它編譯進入引入的css文件中就可以。
此時給文件名稱以_開頭就可以告訴scss在編譯階段并不會將它編譯成為單獨的css文件萧落,而是僅僅會將它的樣式編譯進入引入它的樣式文件中去践美。
比如一個文件夾兩個 scss 文件,一個 root.scss,一個 _vars.scss找岖。
// 第一個 scss 文件夾名 -o 是輸出文件夾名稱npx node-sass scss -o output
// 只會有一個文件生成
rendering Complete, saving .css file...
Wrote CSS to /Users/liusha/Public/vikingship/output/root.css //將 _vars 該名稱為 vars.scss 再執(zhí)行一遍
Rendering Complete, saving .css file...
Wrote CSS to /Users/liusha/Public/vikingship/output/root.css
Rendering Complete, saving .css file...
Wrote CSS to /Users/liusha/Public/vikingship/output/vars.css
會有兩個文件生成
應用場景
這在組件庫的開發(fā)中是非常有用的拨脉,定義單獨組件的樣式文件以Partials import進行定義,不單獨打包成為css文件宣增,在最終導入的樣式文件中統(tǒng)一進行合并管理而不打包出單獨的css文件玫膀。
變量聲明global與default
!default 默認變量
可以在變量的結尾添加 !default 給一個未通過 !default 聲明賦值的變量賦值,此時爹脾,如果變量已經(jīng)被賦值帖旨,不會再被重新賦值,但是如果變量還沒有被賦值灵妨,則會被賦予新的值解阅。
比如這樣一段代碼:
$color:red;
$color:blue !default;
.modules-a {
color: $color; // red
}
我們可以看到即使是先聲明的red,因為blue !default泌霍,所以紅色覆蓋了藍色货抄。!default聲明變量的意思就是說如果項目中存在相同的聲明則優(yōu)先使用別的聲明,如果不存在則使用!default的值朱转,可以理解為默認值蟹地。
!global全局聲明
變量支持塊級作用域,嵌套規(guī)則內(nèi)定義的變量只能在嵌套規(guī)則內(nèi)使用(局部變量)藤为,不在嵌套規(guī)則內(nèi)定義的變量則可在任何地方使用(全局變量)怪与。將局部變量轉換為全局變量可以添加 !global 聲明
在scss中我們都清楚局部變量的定義是無法影響同名的global變量的。但是我們可以通過!global在局部作用域中去定義一個全局都可以使用的變量缅疟。同樣也可以通過!default在局部作用域中去覆蓋一個全局變量的值分别。
#main {
$width: 5em !global;
width: $width;
}
#sidebar {
// 同樣可以使用$width全局變量
width: $width;
}
編譯為
#main {
width: 5em;
}
#sidebar {
width: 5em;
}
mixin
參數(shù)變量...
有時遍愿,不能確定混合指令需要使用多少個參數(shù),比如一個關于 box-shadow 的混合指令不能確定有多少個 'shadow' 會被用到耘斩。這時沼填,可以使用參數(shù)變量 … 聲明(寫在參數(shù)的最后方)告訴 Sass 將這些參數(shù)視為值列表處理.
其實就類似于js中的...rest運算符。
@mixin box-shadow($shadows...) {
-moz-box-shadow: $shadows;
-webkit-box-shadow: $shadows;
box-shadow: $shadows;
}
.shadows {
@include box-shadow(0px 4px 5px #666, 2px 6px 10px #999);
}
編譯后:
.shadowed {
-moz-box-shadow: 0px 4px 5px #666, 2px 6px 10px #999;
-webkit-box-shadow: 0px 4px 5px #666, 2px 6px 10px #999;
box-shadow: 0px 4px 5px #666, 2px 6px 10px #999;
}
使用括授,分隔為.shadowed元素添加多個陰影倾哺。
@content-- 向混合樣式中導入內(nèi)容
在引用混合樣式mixin的時候,可以先將一段代碼導入到混合指令中刽脖,然后再輸出混合樣式羞海,額外導入的部分將出現(xiàn)在 @content 標志的地方
比如這樣的代碼,我們在include中填充了對應的樣式曲管,在mixin中可以通過@content使用却邓。
@mixin apply-to-ie6-only {
* html {
@content;
}
}
@include apply-to-ie6-only {
#logo {
background-image: url(/logo.gif);
}
}
編譯為
// mixin中接受了include 可以理解為插槽
* html #logo {
background-image: url(/logo.gif);
}
為便于書寫,@mixin 可以用 = 表示院水,而 @include 可以用 + 表示腊徙,所以上面的例子可以寫成:
// = 簡寫mixin
=apply-to-ie6-only
- html
@content
// + 簡寫include
+apply-to-ie6-only
logo
background-image: url(/logo.gif)
注意: 當 @content 在指令中出現(xiàn)過多次或者出現(xiàn)在循環(huán)中時,額外的代碼將被導入到每一個地方檬某。
@at-root
常規(guī)用法
@at-root指令可以使一個或多個規(guī)則被限定輸出在文檔的根層級上撬腾,而不是被嵌套在其父選擇器下。
比如
.parent {
...
@at-root .child { ... }
}
編譯之后.child并不會嵌套在任何規(guī)則之下恢恼,因為使用了@at-root選擇符
.parent { ... }
.child { ... }
@at-root同樣也可以當作一個作用域給多個選擇器去使用:
.parent {
...
@at-root {
.child1 { ... }
.child2 { ... }
}
.step-child { ... }
}
編譯后:
.parent { ... }
.child1 { ... }
.child2 { ... }
.parent .step-child { ... }
支持參數(shù)
@at-root (without: ...) and @at-root (with: ...)
默認使用@at-root不傳遞任何時民傻,他的作用為跳出選擇器的作用域嵌套,當然可以傳遞參數(shù)去使用场斑。
比如下面的@at-root意為跳出@media的嵌套:
@media print {
.page {
width: 8in;
@at-root (without: media) {
color: red;
}
}
}
@media print {
.page {
width: 8in;
}
}
.page {
color: red;
}
默認 @at-root 只會跳出選擇器嵌套漓踢,而不能跳出@media或 @support,如果要跳出這兩種漏隐,則需使用 @at-root(without: media)喧半,@at-root(without: support)。這個語法的關鍵詞有
四個:
all(表示所有)
rule(表示常規(guī),默認行為青责。
media(表示 media)
support(表示 support )挺据。
我們默認的 @at-root 其實就是 @at-root( without: rule ):跳出作用域嵌套規(guī)則。
@at-root(without: rule)
rule 關鍵詞只能跳出選擇器嵌套脖隶,不能跳出 @media 和 @support
@at-root(without: media)
可以跳出 @media 扁耐,但是沒有跳出父級選擇器
@at-root(without: support)
@at-root(without: support) 和 @at-root(without: media) 相似,只是跳出的是 @support浩村。
@at-root(without: all)
@at-root(without: all) 是跳出所的指令和規(guī)則做葵,如上面的代碼里 @at-root(without: media rule) 我們可以換成 @at-root(without: all),效果是一樣的心墅。
@each in
maps數(shù)據(jù)格式
首先我們來說說在scss中定義類似js中的對象酿矢。
$map: (key1: value1, key2: value2, key3: value3);
我們通過()就可以定義了。比如這樣的Maps結構定義怎燥。
indigo: #6610f2 !default;
pink: #d63384 !default;
orange: #fd7e14 !default;
green: #52c41a !default;
cyan: #17a2b8 !default;
blue !default;
gray-600 !default;
green !default;
cyan !default;
yellow !default;
red !default;
gray-100 !default;
gray-800 !default;
primary,
'secondary': success,
'info': warning,
'danger': light,
'dark': $dark,
);
我們定義了一個maps的主題瘫筐,分別存在對應的名稱和對應的顏色值。
@each in
@each 指令的格式是 var 可以是任何變量名铐姚,比如
name策肝,而 <list> 是一連串的值,也就是值列表隐绵。
"數(shù)組"迭代
@each 將變量 $var 作用于值列表中的每一個項目之众,然后輸出結果,例如:
@each animal}-icon {
background-image: url('/images/#{$animal}.png');
}
}
編譯為
.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'); }
此時類似于js中的數(shù)組迭代依许。
對象迭代
當然@each key in maps,也支持"迭代"一個對象(maps)棺禾。比如:
@each value in
prefix}-icon--#{
value;
}
}
這樣我們就迭代了上邊定義的$theme-colors這個對象,并且取得了他的key,value峭跳。
多個值迭代
The @each directive can also use multiple variables, as in @each v a r 1 , var1, var1,var2, ... in . If is a list of lists, each element of the sub-lists is assigned to the respective variable. For example:
@each 指令也可以使用多個變量膘婶,如@each var2, ... in 。如果是列表列表蛀醉,則子列表的每個元素都分配給相應的變量悬襟。例如
@each $animal, $color, $cursor in (puma, black, default),
(sea-slug, blue, pointer),
(egret, white, move) {
.#{$animal}-icon {
background-image: url('/images/#{$animal}.png');
border: 2px solid $color;
cursor: $cursor;
}
}
is compiled to:
.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;
}
css :scope選擇器
偶然在寫jest中看到別人使用xxx.querySelect(':scope')。感到比較新奇隨機查閱記錄一番拯刁。
在JavaScript中脊岳,當用于Element.querySelector
[3],Element.querySelectorAll
[4]或Element.closest
[5]時垛玻,:scope是指調(diào)用這些方法的元素逸绎。例如,document.body.querySelector(":scope")返回body元素夭谤。盡管CSS對 :scope的支持已被移除棺牧,但 :scope 的這種用法仍然被支持
使用:scope選擇器可以匹配對應的方法比如element.querySelector(':scope')則會返回element元素本身。
需要主要的是:scope偽類在css中已經(jīng)不被大多數(shù)瀏覽器支持朗儒,甚至已經(jīng)廢棄颊乘。但是在js這些方法中仍然被主流瀏覽器支持。