OKR
SCSS
早期Sass底層是以Ruby語言來撰寫,因此要使用Sass需要有Ruby環境,但官方已經於2019/03/26表示不再維護Ruby Sass!現階段比較主流的是DartSass及 LibSass,DartSass可讓Sass被編譯到JavaScript庫中,而LibSass最常見的就是因應Node.js而推出的Node-sass,目前我們正在使用的則是LibSass。
.menu{..}
.menu ul{..}
.menu li{..}
.menu a{..}
目前公司也是採用SCSS,優點如下:
.menu{..}
.menu ul{..}
.menu li{..}
.menu a{..}
可少寫括號與分號,但若資料量越大後,自己閱讀性不太容易判別錯誤,目前也不太習慣使用這種寫法
.menu
..
ul
..
li
..
a
..
依專案所需規劃可建立一支專門引用SCSS的管理頁,這樣可以很清楚知道專案有引用那些SCSS
規劃檔案的結構
(有底線代表不會被編譯成一支檔,合併使用)
_variable.scss //專門放相關變數
_mixin.scss //專門放相關mixin函式
_mixinRwd.scss //rwd media
_base.scss //全域設定SCSS
_index.scss //專案頁面SCSS
例如建立一支main.scss
依據上方的結構,這頁專門import上述的scss==>最後編譯成main.css
引用格式如下:
@import "variable";
@import "mixin";
@import "mixinRwd";
@import "base";
//你也可以建立分類的資料夾
@import "/page/index";
@import "abstracts/variables", "abstracts/functions", "abstracts/mixins";
也可以導入CSS文件
Imports where the URL ends with .css.
Imports where the URL begins http:// or https://.
Imports where the URL is written as a url().
@import "theme.css";
@import "http://fonts.googleapis.com/css?family=Droid+Sans";
@import url(theme);
有兩種註解方式:
在@mixin中我們可以增加各種功能詳細描述,可參考project_template
公司公版,裡面正在慢慢擴充一些常用的@mixin,以便共享於各專案使用。
使用「///」符號來註解,更多的註解用途可參考SassDoc
@example 描述功能名稱,實際應用在什麼地方
@param 是用來記錄@mixin或function的參數
/// @example tab分頁樣式-4種樣式
/// @param {String} $tab-type 參數請填tab名稱,預設為'underLineTab'
/// @param {Size} $line_Height 參數請填tab底線高度, 預設為'3px'
/// @param {Color} $line_Color 參數請填底線顏色
$
符號//變數設定
$text-color:#3F51B5;
$font-xl:20px;
//將變數放置對應地方
.abc{
font-size: $font-xl;
background: $text-color;
border: 1px solid $text-color;
color: red;
}
編譯結果如下
.abc{
font-size:20px;
background:#3F51B5;
border:1px solid #3F51B5;
color:red
}
/* 加減乘除運算 */
width: calc(100% - 50px);
/* 定位 */
top:calc(50% - 1px);
/* 變數計算,記得加上字串辨識 */
line-height: calc(#{$select-height} - 15px);
符號可以放在第一層,也可以放第二層,或是在兩者的之間
ul > {
li {
list-style-type: none;
}
}
h2 {
+ p {
border-top: 1px solid gray;
}
}
p {
~ {
span {
opacity: 0.8;
}
}
}
#container * {
border: 1px solid black;
}
/* h2相鄰的兄弟p,增加border-top灰線 */
h2 {
+ p {
border-top: 1px solid gray;
}
}
/* h2相鄰的所有兄弟p,增加border-top灰線 */
p {
~ {
span {
opacity: 0.8;
}
}
}
p {
&:hover{}
.active &{}
:not(&){}
}
/* 編譯結果 */
p:hover{}
.active p{}
:not(p){} //選擇所有不是p的元素,[補充]:not它的作用是防止特定的元素被選中
&符號搭配BEM結構撰寫時非常好用,而無須多次撰寫較長的class,看以下範例就可以得知,目前公司專案也是儘量採BEM結構模式撰寫。
.accordion{
/* ... */
&__copy{
/* ... */
&--open{
/* ... */
}
}
}
/* 編譯結果 */
.accordion{/* ... */}
.accordion__copy{/* ... */}
.accordion__copy--open{/* ... */}
@mixin xxx($className,$top-or-bottom,$left-or-right){
.icon-#{$className}{
#{$top-or-bottom}:0;
#{$left-or-right}:0;
}
}
@include xxx('mail',top,right)
/* 編譯結果 */
.icon-mail{
top:0;
right:0;
}
/* first-child代表第一個 */
li:first-child {
border: 0;
border-top-left-radius: $border-radius;
border-top-right-radius: $border-radius;
}
/* last-child代表最後一個 */
li:last-child {
border: 0;
border-bottom-left-radius: $border-radius;
border-bottom-right-radius: $border-radius;
}
/* nth-child(n)代表指定選擇第幾個,從(1)開始 */
li:nth-child(1) {
border: 0;
border-bottom-left-radius: $border-radius;
border-bottom-right-radius: $border-radius;
}
/* nth-child(odd)奇數 */
p:nth-child(odd) {
background: red;
}
/* nth-child(even)偶數 */
p:nth-child(even) {
background: blue;
}
/* :nth-child(an+b)若是使用計算方式,n則可從(0)開始 */
tr:nth-child(3n+1){
background-color:#69C;
}
/* 上方文章分享-圖片緩衝 */
$ver:unique_id();
@mixin imageCacheBust($url) {
background-image: #{'url("'}#{$url}#{'?v='}#{$ver}#{'")'};
}
.sprite {
@include imageCacheBust('asset/images/logo.png');
}
/* 編譯結果 */
.sprite {
background-image: url('asset/images/logo.png?v=u95ab40e0');
}
Sass map是類似json的一種變數,可以使用Sass Map來定義基本的元件變數,與json最大的差異是使用()
取代{}
。
三種function
//列出指定map的key
map-keys($map)
//列出指定map的value
map-values($map)
//判別布林值true or false
map-has-key($map, $key)
$color:(
primary:#cccccc;
secondary:#000000;
)
/* 編譯結果 */
//以下只是展示範例回傳的結果,僅供參考
map-keys($color,primary);
.test{
color:primary
}
map-values($color,#cccccc);
.test{
color:#cccccc
}
map-has-key($color,primary);
.test{
color:true
}
/* variables組合 */
//"$key":$value
//可以依據不同的元件用一個群組,方便辨識,例如border.button.text.link..等等
$primary-color: #098081;
$primary2-color: #c4dbd5;
$primary3-color: #6e6d6d;
//可以在依網站的顏色去自訂名稱,方便記憶
$border-set:(
"border-primary1": $primary-color,
"border-primary2": $primary2-color,
"border-primary3": $primary3-color
);
/* variables使用 */
//使用map-get()取值
.button {
color:map-get($border-set,border-primary3)
}
上面是只有單純顏色的組合,若像是按鈕這種會包含多樣式種類的,可以寫成以下組合
/* variables組合 */
// 定義按鈕的不同狀態設定
$btn-config:(
default:(
class: 'default',
color: #333,
bg: #fff,
border-color: #ccc
),
primary:(
class: 'primary',
color: #fff,
bg: #009AFF,
border-color: #009AFF
),
danger:(
class: 'danger',
color: #fff,
bg: #D84315,
border-color: #009AFF
)
);
然後賦予基本button的結構+搭配mixin()來完成多組按鈕組合,詳細可參考分享網站透過SassMap製作多個樣式
/* 首先刻出一個按鈕基本結構 */
.btn{
/*......*/
&:hover,&:focus{
color: #333;
background-color: #e6e6e6;
}
}
/* @mixin */
//通常按鈕結構最常變更的是背景顏色、外框顏色、還有文字顏色
@mixin button-set($color,$background,$border-color){
color:$color;
background-color:$background;
border-color:$border-color;
&:hover,&:focus,&:active{
color:$color;
background-color:darken($background,5%);
border-color:darken($border-color,5%);
}
}
/* @each+map-get()+@include */
//$key,$value
@each $keyname, $value in $btn-config{
$class:map-get($value,class);
$color:map-get($value,color);
$bg:map-get($value,bg);
$border-color:map-get($value,border-color);
.btn-#{$class}{
@include button-set($color,$background,$border-color)
}
}
/* html結構 */
//這樣就可以寫出類似像bootstrap btn不同class的btn
<button class="btn">這是一個按鈕</button>
<button class="btn btn-primary">這是一個按鈕</button>
<button class="btn btn-danger">這是一個按鈕</button>
若CSS有相類似的語法,範例如下
/* 原本這樣寫 */
@mixin banner($image,$bg-size: cover, $bg-height: 500px, $bg-position: 50% 50%) {
backgorund-image:$image;
background-repeat: no-repeat;
background-size: $bg-size;
background-position: $bg-position;
max-width: 100%;
height: $bg-height;
}
/* 後來這樣寫 */
@mixin banner($image,$bg-size: cover, $bg-height: 500px, $bg-position: 50% 50%) {
max-width: 100%;
height: $bg-height;
background:{
image:$image;
repeat:no-repeat;
size:$bg-size;
position:50% 50%;
}
}
/* mixin建立組合 */
@mixin avatar($size, $circle: false) {
width: $size;
height: $size;
@if $circle {
border-radius: $size / 2; //返回true
}
}
.square-av { @include avatar(100px, $circle: false); }
.circle-av { @include avatar(100px, $circle: true); }
/* 編譯結果 */
.square-av {
width: 100px;
height: 100px; //返回false,所以沒有border-radius
}
.circle-av {
width: 100px;
height: 100px;
border-radius: 50px; //返回true
}
另一種寫法
例如判斷是否需要border-radius(沒有外框為0/有外框就給數值),寫法如下:
/* mixin建立組合 */
@mixin square($size, $radius: 0) {
width: $size;
height: $size;
@if $radius != 0 {
border-radius: $radius; //假如不等於0
}
}
.text{
@include square(100px,$radius:4px);
}
/* 編譯結果 */
.text {
width: 100px;
height: 100px;
border-radius: 4px;
}
有時網頁會有很多區塊會共用到不同的背景或圖片樣式,這時候都還要特別幫那個區塊給一個class或是直接將css寫在那個區塊裡,使用mixin()來建立組合,有需要就直接引用到區塊裡
/* mixin建立組合 */
@mixin section-background($color){
#{if (&, '&.section-background', '.section-background')}{
background-color:$color;
color:#000000;
}
}
/* include使用 */
.sidebar{
@include section-background(#cccccc);
}
/* 編譯結果 */
.sidebar.section-background{
background-color:#cccccc;
color:#000000;
}
舉例來說,若有多種類型的tab分頁style,原本一種tab就寫一支@minxin,那要如何使用@mixin來合併,引用時只要判斷類型輸入即可呢?答案就是使用@if
,範例說明如下:
/* mixin多類型建立組合 */
//可以在@mixin裡放置預置的變數
//日後若有新的tab種類,即可依序新增下去..
//@error為編譯時若有錯誤會編譯失敗並停止,顯示錯誤訊息提醒,@warn也是一種錯誤提醒,但sass雖會報錯,但還是會繼續編譯,所以反而使用@error會更好
@mixin navTab(
$tab-type: underLineTab //預設的tab種類
$selector: "*", //若父層底下有子層的內容,可以使用*來代表
){
@if $tab-type == underLineTab {
/*這裡放第一種tab的css*/
}@else if $tab-type == borderTab{
/*這裡放第二種tab的css*/
}@else if $tab-type == squareTab{
/*這裡放第三種tab的css*/
}@else if $tab-type == nogutterTab{
/*這裡放第四種tab的css*/
}@else {
@error "請填寫$tab-type正確參數:underLineTab/borderTab/squareTab/nogutterTab";
}
}
網路上提到常見斷點參考
iPad - 768px
iPad以下 - 767px
iPhone 6 Plus - 414px (視專案族群)
iPhone 6 - 375px (視專案族群)
iPhone 5、SE - 320px
使用在rwd範例,以下參考bootstrap斷點設計
//rwd breakpoint 設定各種斷點,也可以在陸續新增自訂的尺寸
$col-xl: 1200px;
$col-lg: 992px;
$col-md: 768px;
$col-sm: 576px;
@mixin rwd($col-xl) {
@media (max-width: $col-xl) {
@content;
}
}
@mixin rwd($col-lg) {
@media (max-width: $col-lg) {
@content;
}
}
@mixin rwd($col-md) {
@media (max-width: $col-md) {
@content;
}
}
@mixin rwd($col-sm) {
@media (max-width: $col-sm) {
@content;
}
}
.circle-image2 {
@include circle(blue, $white, $size);
//一樣使用@include引用
@include rwd($col-xl) {
width: $size/2;
height: $size/2;
line-height: $size/2;
font-size: 15px;
}
@include rwd($col-sm) {
width: $size/2;
height: $size/2;
line-height: $size/2;
font-size: 13px;
}
}
//編譯結果
.circle-image2 {
background: blue;
border-radius: 99%;
width: 500px;
height: 500px;
line-height: 500px;
font-size: 100px;
color: #fff;
text-align: center;
}
@media (max-width: 1200px) {
.circle-image2 {
width: 250px;
height: 250px;
line-height: 250px;
font-size: 15px;
}
}
@media (max-width: 576px) {
.circle-image2 {
width: 250px;
height: 250px;
line-height: 250px;
font-size: 13px;
}
}
@each <variable> in <expression> { … }
each迴圈可以設定一個變數群組然後分別套用
$sizes: 40px, 50px, 80px;
@each $size in $sizes {
.icon-#{$size} {
font-size: $size;
height: $size;
width: $size;
}
}
/* 編譯結果 */
.icon-40px {
font-size: 40px;
height: 40px;
width: 40px;
}
.icon-50px {
font-size: 50px;
height: 50px;
width: 50px;
}
.icon-80px {
font-size: 80px;
height: 80px;
width: 80px;
}
替換背景顏色方法範例
<div class="container">
<div class="box box1 box-primary"></div>
<div class="box box2 box-primary"></div>
<div class="box box3 box-danger"></div>
<div class="box box4 box-secondary"></div>
<div class="box box5 box-danger"></div>
</div>
//設定顏色群組
//"$key":$value,
$colorset: (
"primary": #ccc,
"danger": #dd4444,
"secondary": #3e5bbb
);
//scss變數寫法:#{$key}
@each $key, $value in $colorset {
.box-#{$key} {
background: $value;
}
}
顯示效果如下
透過scss可以搭配@for迴圈來使用連續變數的功能,例如以下顏色漸變範例
<div class="container">
<div class="box box1"></div>
<div class="box box2"></div>
<div class="box box3"></div>
<div class="box box4"></div>
<div class="box box5"></div>
</div>
//box基本屬性
.box {
height: 150px;
width: 150px;
float: left;
background: #ccc;
}
//box1~box5給予連續漸變顏色效果,設定$i(1~5)數值為變數
//@for迴圏 from-through(跑1到5數值);from-to(跑1到4數值),兩者須注意有不同
//scss變數寫法:#{$i}
@for $i from 1 through 5 {
.box#{$i} {
background: darken(white, $i * 10%);
}
}
顯示效果如下
跟console.log一樣,幫你查看打印出來的值是否正常。以下為一個簡單的例子,實際專案下執行webpack編譯時就會看到訊息。但另外有發現Vscode Live Sass使用@debug不會出現,看了一下它的說明與更新內容好像本來就沒有進一步支援。
$font-sizes: 10px + 20px;
$style: (
color: #bdc3c7
);
.container{
@debug $style;
@debug $font-sizes;
}
/* 打印結果,會出現類似畫面 */
Line 7 CSS: (color: #bdc3c7)
Line 8 CSS: 30px
可以將一個或多個樣式規式跳出子層,而不是嵌在父層selector裡面,範例如下:
.parent{
...
@at-root .child{....}
}
/* 編譯結果 */
.parent{...}
.child{...}
.parent{
...
.step-child { ... }
@at-root{
.child1{...}
.child2{...}
}
}
/* 編譯結果 */
.parent{...}
.parent .step-child{...}
.child1{...}
.child2{...}
分享一篇看到寫的很清楚的文章,文章提到詳解Sass新特性- 模塊的內容。
內容提到sass團隊正在推行sass模塊化機制,建議大家使用@use.@forward,但目前僅Dart Sass 1.23.0完全支援這兩種特性,加上官網@import說明上也有提到Sass團隊不鼓勵繼續使用@import規則,預計在未來幾年會逐步淘汰它,雖然還不是現在,但或許在淘汰前可能要慢慢去研究@use+@forward。
文件中提到@use與@import最主要的差異(待須實際試用):
@import:假如不同的頁面引用了相同的scss,樣式可能會被重覆加載,導致重複代碼
@use:不管使用了多少次樣式表,都只會引用和執行一次