如何用 Sass 實現類似 Bootstrap 4 的格線系統
★ 首先這篇文章適合以下背景的人閱讀:
1.大概了解什麼是格線系統,甚至有用過
2.有使用過 Sass 管理及撰寫 CSS,並且對基礎 Sass 語法 (SCSS) 有初步了解,並且熟悉 @for
寫法
3.想自行撰寫自己的格線系統
什麼是格線系統?
格線系統起先來自於平面設計,簡單來說,就像是在你要設計的紙張上開始畫格子,將整張紙佈滿了很多的直行和橫列,直行和橫列交錯成了很多等距 & 等寬的小格子,然後才開始在上面加上想要的內容,不管是圖案或文字。圖紙上因已有了格線系統,所以設計內容會貼齊著格線開始,也可能終於某個隔線,如此一來,大家天馬行空的設計內容,還是會遵循著一個簡單的規範,那個規範就是格線系統,用意就有點像是想要手寫卡片,但是先畫線一樣,目的就只是讓寫的字能夠更正整齊一點。
現在我們先來用單純的 CSS 寫一個簡單的格線系統
首先,來看一下簡單的格線系統 HTML 構造吧,若以簡單的 960px 寬度的格線系統來說,分成 12 個格子,每一個格子和格子的間距是 30px
,先用一個 .container
包住所有的內容讓他可以限制在一個範圍內,我們會設定 max-width:960px
,再來需要一個外層的屬性 .row
,包住裡面的每一個 .col
,而真正的內容還在再放進 .col
裡面,由於格線系統總共有 12 個等份,這裡我們用 3 個 .col-4
把 12 等份分成 3 份,每一份中間間距為 30px
。
<body>
<div class="container">
<div class="row">
<div class="col-4">
<div class="box"></div>
</div>
<div class="col-4">
<div class="box"></div>
</div>
<div class="col-4">
<div class="box"></div>
</div>
</div>
</div>
</body>
實作方式如下,請看 CSS。
首先,設定 box-sizing:border-box
以及 CSS Reset,這裡只是簡單的將 margin
和 padding
歸零,寫網頁時請直接採用 meyerweb 的 CSS Reset 。
*{
box-sizing:border-box;
}
body{
margin:0;
padding:0;
}
然後將 .container
設定寬度,如前所述 max-width:960px
,然後 margin: 10px auto
,我想要 .container
上下也有 10px
的 margin
然後內容全部置中,所以 margin: 10px auto
,再來 padding-right
及 padding-left
都設定 15px
,是為了要回補 .row
的 margin
間距負值,後面會提到。
.container{
max-width:960px;
margin: 10px auto;
padding-right: 15px;
padding-left: 15px;
}
然後就是 .row
,首先先將設定 display:flex
,讓這個區塊內改用 flex
排版,再來就是 margin-left
及 margin-right
都設定 -15px
,margin
可以設定負值,這個負值會由 .container
來做補回,最後加上 flex-wrap:wrap
,這是指超出的部分會不會自動換行的意思,等後面提到 @media(max-width:768px)
時, .col
的 width
都設為 100%g
時,所有的 .col
就會全部自動縱向排列了。
.row{
display:flex;
margin-left: -15px;
margin-right: -15px;
flex-wrap:wrap;
}
再來就是 .col-4
與他的 @media
設定, .col-4
在這個例子裡只是舉例,其他的 .col-1~.col-12
都是一樣的設定方法,只是要自行計算 width
的百分比就是了。
計算方式舉例:
1.假設,在 12 等分的格線系統中,我們想要把他分 2 等分,則 12/2=6 ,通常這個等分我們就會取名為 col-6
,而 6/12=50%,所以 width
等於 50%。
2.若以這個範例來說,在 12 等分的網格系統中,我想要把它分成 3 等分,所以 12/3=4,這個等分我們取名為 col-4
,而 4/12=33.33333%,所以 width
等於 33.33333%。
而進入了 @media(max-width:768px)
斷點,不管是幾等分,.col-1~.col-12
,width
都設定為 100%
。
.col-4{
padding-left: 15px;
padding-right: 15px;
width: 33.33333%;
}
@media(max-width:768px){
.col-4{
width:100%;
}
}
最後,就是實際的內容,.box
要顯示什麼,設一個簡單的 height:50px
來撐開高度還有一個 background:blue
,開始有顏色了,最後設一個 margin:10px 0
讓他上下有個間隔,這樣就大功告成了。
.box{
height: 50px;
margin:10px 0;
background:blue;
}
所以,畫面會這樣顯示
若是我們把全部的 .col-1~.co1-12 全部都放進來呢?
前面只是一個用 .col-4
的簡單範例,現在我們把全部的 .col-1~.co1-12
都放進來吧,這裡請看 codepen。
我們先看一下 HTML 有什麼不一樣,下面總共有 11 個 .row
,每一個 .row
內都放進了 2 個 .col
,而這兩個 .col
都會拼湊成 12 等分,例如 .col-1
會配上 .col-11
一起放在同一個 .row
裡,而每一個 .col
都會再放進一個 .box
落落長程式碼如下。
<div class="container">
<div class="row">
<div class="col-1">
<div class="box"></div>
</div>
<div class="col-11">
<div class="box"></div>
</div>
</div>
<div class="row">
<div class="col-2">
<div class="box"></div>
</div>
<div class="col-10">
<div class="box"></div>
</div>
</div>
<div class="row">
<div class="col-3">
<div class="box"></div>
</div>
<div class="col-9">
<div class="box"></div>
</div>
</div>
<div class="row">
<div class="col-4">
<div class="box"></div>
</div>
<div class="col-8">
<div class="box"></div>
</div>
</div>
<div class="row">
<div class="col-5">
<div class="box"></div>
</div>
<div class="col-7">
<div class="box"></div>
</div>
</div>
<div class="row">
<div class="col-6">
<div class="box"></div>
</div>
<div class="col-6">
<div class="box"></div>
</div>
</div>
<div class="row">
<div class="col-7">
<div class="box"></div>
</div>
<div class="col-5">
<div class="box"></div>
</div>
</div>
<div class="row">
<div class="col-8">
<div class="box"></div>
</div>
<div class="col-4">
<div class="box"></div>
</div>
</div>
<div class="row">
<div class="col-9">
<div class="box"></div>
</div>
<div class="col-3">
<div class="box"></div>
</div>
</div>
<div class="row">
<div class="col-10">
<div class="box"></div>
</div>
<div class="col-2">
<div class="box"></div>
</div>
</div>
<div class="row">
<div class="col-11">
<div class="box"></div>
</div>
<div class="col-1">
<div class="box"></div>
</div>
</div>
</div>
所以那他的 CSS 會是怎麼樣呢?和之前範例相同的我就不再贅述,因為那些程式碼存在的意義是一樣的,下面只放上不一樣的地方。首先,將 .col-1~.col-12
的 padding-left: 15px
及 padding-right: 15px
全部寫在一起這樣可不用一直寫重複的程式碼,再來也就是我們必須手動算出 .col-1~.col-12
的每一個 width
是多少百分比,然後填上即可,前面的段落有說明 width
的百分比如何計算,同樣的在 @media(max-width:768px)
時,我們也將 .col-1~.col-12
的 width
全部設為 100%
。
.col-1,.col-2,.col-3,.col-4,.col-5,.col-6,
.col-7,.col-8,.col-9,.col-10,.col-11,.col-12{
padding-left: 15px;
padding-right: 15px;
}
.col-1{
width: 8.333333%;
}
.col-2{
width: 16.66667%;
}
.col-3{
width: 25%;
}
.col-4{
width: 33.33333%;
}
.col-5{
width: 41.66667%;
}
.col-6{
width: 50%;
}
.col-7{
width: 58.33333%;
}
.col-8{
width:66.66667%;
}
.col-9{
width: 75%;
}
.col-10{
width: 83.33333%;
}
.col-11{
width: 91.66667%;
}
.col-12{
width: 100%;
}
@media(max-width:768px){
.col-1,.col-2,.col-3,.col-4,.col-5,.col-6,
.col-7,.col-8,.col-9,.col-10,.col-11,.col-12{
width:100%;
}
}
所以,他的畫面就變成這個樣子囉,是不是其實也不難,但就是麻煩了點。
欸欸欸~不是說要用 Sass 寫嗎?
這不就來了嗎?現在我們已經知道用純 CSS 寫格線系統要怎麼寫了,但是呢要一直按計算機著實有點麻煩,而且也無法設定變數,所以他的間距以及等分都是寫死的,這樣要怎麼客制呢?當然用 Sass 就可以解決這個問題囉。
不免俗,先來看 codepen 吧
這個範例,在 HTML 內我稍微做了一點點花俏變化,那就是在每一個 .box
我又加了另外一個 class
進去(如下),依照程式碼順序依序為 .box-1~.box-22
,為什麼這樣我後面 CSS 再來說明。
<div class="box box-1"></div>
我們先直接來看 SCSS 碼吧,同樣的相同的我也就不贅述囉,既然要用 SCSS 寫,當然不能放過他的 $變數
及 @mixin
功能呀。
$gutter-width:30px
表示這個格線系統的間距設定為 30px
,因為是以變數的形式存在,也就是未來可以透過修改這裡,來修改這個格線系統的間距。
再來是 $grid-num:12
這個代表這個格線系統共分為 12 個欄位 (12等份),同樣的也可以直接修改。
最後是一個響應式斷點 @mixin pad
,讓後面要修改響應式設定時可以更方便撰寫。
$gutter-width:30px;
$grid-num:12;
@mixin pad{
@media(max-width:768px){
@content;
}
}
再來剛剛落落長程式碼已經沒剩多少了,縮成這樣囉,第一個 @for
,是要讓 .box-1~.box-22
可以有不同的漸層顏色效果,透過 $i
迭代 1
至 22
,配合 darken
語法,每一個 .box
的顏色都以每 2%
深度開始產生漸層。
再來是 %col
,這是裡將所有的 .col
共通元素紀錄在內,也就是 padding-left
和 padding-right
而值就是 $gutter-width / 2
而因為 $gutter-width
的值為 30px
,所以除以 2 就是 15px
。
最後一個 @for
則是實現我們格線系統的最大功臣,將 $i
變數從 1
迭代至 $grid-num
(前面設定為 12 ),所以我們可以直接設定 .col-1~.col-12
,並且先用 @extend %col
將內部的 padding-left
及 padding-right
複製過來,後面再接著加上 width: 100% * ($i / $grid-num )
透過 $i
的迭代,.col-1~.col-12
將會獲得不同的 width
值,也使得我們的格線系統可以透過 @for
的方式,自行計算出來,同樣的我們在用 @include pad
呼叫一下之前設定好的 @mixin pad
將響應式的設定寫在裡面也就是 width:100%
,這樣格線系統就大功告成了。
@for $i from 1 through 22{
.box-#{$i}{
background:darken(Turquoise,2%*$i);
}
}
%col{
padding-left: $gutter-width / 2;
padding-right: $gutter-width / 2;
}
@for $i from 1 through $grid-num{
.col-#{$i}{
@extend %col;
width: 100% * ($i / $grid-num );
@include pad{
width: 100%;
}
}
}
我們來看一下實際的畫面吧。
用 SCSS 碼寫的好處,就是可以利用變數來管理,未來若間距不是 30px
了,也可以直接修改,等份不是 12
了,也可以直接修改,後面的程式碼通通都還是適用的喔,今天就介紹到這裡,謝謝大家!