AlecWang 已發佈 2019-10-18

如何用 Sass 實現類似 Bootstrap 4 的格線系統

★ 首先這篇文章適合以下背景的人閱讀:

1.大概了解什麼是格線系統,甚至有用過
2.有使用過 Sass 管理及撰寫 CSS,並且對基礎 Sass 語法 (SCSS) 有初步了解,並且熟悉 @for 寫法
3.想自行撰寫自己的格線系統

什麼是格線系統?

格線系統起先來自於平面設計,簡單來說,就像是在你要設計的紙張上開始畫格子,將整張紙佈滿了很多的直行和橫列,直行和橫列交錯成了很多等距 & 等寬的小格子,然後才開始在上面加上想要的內容,不管是圖案或文字。圖紙上因已有了格線系統,所以設計內容會貼齊著格線開始,也可能終於某個隔線,如此一來,大家天馬行空的設計內容,還是會遵循著一個簡單的規範,那個規範就是格線系統,用意就有點像是想要手寫卡片,但是先畫線一樣,目的就只是讓寫的字能夠更正整齊一點。

現在我們先來用單純的 CSS 寫一個簡單的格線系統

這裡我們先來看很簡單的案例 codepen

image

首先,來看一下簡單的格線系統 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,這裡只是簡單的將 marginpadding 歸零,寫網頁時請直接採用 meyerweb 的 CSS Reset

*{
 box-sizing:border-box;
}
body{
 margin:0;
 padding:0;
}

然後將 .container 設定寬度,如前所述 max-width:960px,然後 margin: 10px auto,我想要 .container 上下也有 10pxmargin 然後內容全部置中,所以 margin: 10px auto,再來 padding-rightpadding-left 都設定 15px,是為了要回補 .rowmargin 間距負值,後面會提到。

.container{
 max-width:960px;
 margin: 10px auto;
 padding-right: 15px;
 padding-left: 15px;
}

然後就是 .row,首先先將設定 display:flex,讓這個區塊內改用 flex 排版,再來就是 margin-leftmargin-right 都設定 -15pxmargin 可以設定負值,這個負值會由 .container 來做補回,最後加上 flex-wrap:wrap,這是指超出的部分會不會自動換行的意思,等後面提到 @media(max-width:768px) 時, .colwidth 都設為 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-12width 都設定為 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;
}

所以,畫面會這樣顯示

images

若是我們把全部的 .col-1~.co1-12 全部都放進來呢?

前面只是一個用 .col-4 的簡單範例,現在我們把全部的 .col-1~.co1-12 都放進來吧,這裡請看 codepen。

images

我們先看一下 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-12padding-left: 15pxpadding-right: 15px 全部寫在一起這樣可不用一直寫重複的程式碼,再來也就是我們必須手動算出 .col-1~.col-12 的每一個 width 是多少百分比,然後填上即可,前面的段落有說明 width 的百分比如何計算,同樣的在 @media(max-width:768px) 時,我們也將 .col-1~.col-12width 全部設為 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%;
 }
}

所以,他的畫面就變成這個樣子囉,是不是其實也不難,但就是麻煩了點。

images

欸欸欸~不是說要用 Sass 寫嗎?

這不就來了嗎?現在我們已經知道用純 CSS 寫格線系統要怎麼寫了,但是呢要一直按計算機著實有點麻煩,而且也無法設定變數,所以他的間距以及等分都是寫死的,這樣要怎麼客制呢?當然用 Sass 就可以解決這個問題囉。

不免俗,先來看 codepen 吧

images

這個範例,在 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 迭代 122,配合 darken 語法,每一個 .box 的顏色都以每 2% 深度開始產生漸層。

再來是 %col,這是裡將所有的 .col 共通元素紀錄在內,也就是 padding-leftpadding-right 而值就是 $gutter-width / 2 而因為 $gutter-width 的值為 30px,所以除以 2 就是 15px

最後一個 @for 則是實現我們格線系統的最大功臣,將 $i 變數從 1 迭代至 $grid-num (前面設定為 12 ),所以我們可以直接設定 .col-1~.col-12,並且先用 @extend %col 將內部的 padding-leftpadding-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%;
    }
  }
}

我們來看一下實際的畫面吧。
images

用 SCSS 碼寫的好處,就是可以利用變數來管理,未來若間距不是 30px 了,也可以直接修改,等份不是 12 了,也可以直接修改,後面的程式碼通通都還是適用的喔,今天就介紹到這裡,謝謝大家!

關於筆者

暱稱:AlecWang

文章列表 文章列表