iT邦幫忙

2022 iThome 鐵人賽

DAY 17
2

情境

我們在認識 CSS Box Model 的時候,有一個必須要知道的屬性,就是 box-sizing

我們來看看這個 Box Model:

我們在初學 CSS 的時候,會開始學習一些容易掌握的屬性,例如 widthheight 就是其中幾個。但是,我們剛接觸這兩個屬性的時候,我們不太容易仔細去思考,到底這個 widthheight 是指哪裡?

舉個例子,我們看看下面這個方形:

如果我告訴你他是一個 200x200 的方形,你不會覺得有什麼奇怪的地方:

.square {
  width: 200px;
  height: 200px;
  background: #1F7A8C;
}

但是如果是這樣呢:

他一樣是一個 200x200 的方形,只是我們給他一個較寬的 border:

.square {
  width: 200px;
  height: 200px;
  background: #1F7A8C;
  border: 10px solid #BFDBF7;
}

問題出來了,請問,200x200 指的是最外圍「包含」 border 的地方,還是內部「不包含」 border 的地方?

這樣的問題,就是 box-sizing 這個屬性要去定義的。

你能看見多遠的未來呢?

初接觸網頁設計的入門者,會比較容易忽略這個屬性,因而導致有時候出現一些難以理解的狀況。甚至我們可能會不知所措而到最後只能用奇怪的方式解決問題。

Table Row 的高度

例如我們來看下面這個 Table 元件,他每一行的高度是 56.5px

假設今天有一個情境,我們需要按照設計師的指示來讓這一行變成 60px 的高度,我們會怎麼做呢?很直覺的反應,我們可能會這樣做:

.table-cell {
  height: 60px;
}

就是直接對他指定高度,結果沒想到,我們卻得到這樣的結果:

奇怪?明明原本是 56.6px,然後我在 CSS 指定他 height: 60px;,但是最後的結果居然是 92.5px!?這不是見鬼了嗎?

所以,下一個想法,你可能會覺得可能有哪裡的 CSS 權限太高,碾壓過你目前的權限,此時你會為他加入 !important 來提升 CSS 效果的權限:

.table-cell {
  height: 60px !important;
}

結果你會發現,沒有任何變化....

到這時你已經反覆嘗試過各種方法,發現都走投無路了,你只好寫出下面這種 code:

.table-cell {
  height: calc(60px - 32.5px);
}

透過這種方式,你真的能夠成功的把這一行的高度變成很精準的 60px,但是你很不甘心,因為有一行奇怪的 code 不得不在那裡,而且以後的工程師看到這一行,絕對會覺得莫名奇妙,然後你沒有辦法解釋為什麼你要這樣寫。

不知從何冒出來的滾動條

一樣以 Table 來舉例,不知道有沒有遇過這種情境,有時候我們的 Table 會出現一個令人難以理解的滾動條:

.table-container {
  max-width: 800px;
}

.table {
  width: 100%;
  border: 1px solid #C9C9C9;
  overflow-y: auto;
}
<div class="table-container">
  <table class="table">...</table>
</div>

明明這個 container 已經限制是 800px 的寬度,然後內部的 table 寬度是 width: 100%;,我明明沒有設定 X 軸方向的滾動條 overflow-x: scroll;,但不知道為什麼這個滾動條一直都去不掉,而且右邊的 border 會一直超出範圍。

最慘和最醜的是,當寬度空間不夠時,會出現兩條滾動條:

所以,一樣的,你很有可能透過下面這樣的方式來解決問題:

.table {
  width: calc(100% - 2px);
  border: 1px solid #C9C9C9;
  overflow-y: auto;
}

你會一直搞不懂為什麼你要無來由的去減掉 2px 才能夠去掉那個惱人又無用的滾動條。

透過 box-sizing 解決問題

事實上,上面這兩個舉例都考驗著我們對於 box-sizing 的理解。

box-sizing 是用來決定物件 widthheight 的計算方式。白話來說,就是我要以哪裡為測量基準來丈量物件的長寬。主要作用的值有下面兩個:

  • content-box
    • 是 box-sizing 的預設值。width 與 height 只包括內容本身的寬和高, 不包括邊框(border)、內邊距(padding)、外邊距(margin)。注意:內邊距、邊框和外邊距都在這個盒子的外部。
  • border-box
    • width 和 height 屬性包括內容(content),內邊距(padding)和邊框(border),但不包括外邊距(margin)。注意,內邊距和邊框都將在盒子內。

以上述的範例來說明,在「Table Row 的高度」範例中,我們指定 table row 的高度是 60px,是在 box-sizing: content-box; 的設置之下,因為他是預設值,所以我們指的 60px 是「不包含」padding 的高度,所以,畫面上面顯示的 92.5px 是我們指定的 60px 再加上 padding 的高度。此時的解決辦法,就是我們將 box-sizing 設置為 border-box 就可以了:

.table-cell {
  height: calc(60px - 32.5px);
  box-sizing: border-box;
}

同樣的原理,在「不知從何冒出來的滾動條」範例中,會無來由多出來的 2px,其實是 border 的寬度。我們作個實驗就可以知道,把 border 去掉,這個滾動條就消失了:

.table {
  width: calc(100% - 2px);
  /* border: 1px solid #C9C9C9; */
  overflow-y: auto;
}

所以,在想要保留 border 的前提下,如果我們不用 width: calc(100% - 2px);,來解決問題,好的方法應該也是去改變 box-sizing 的設置,改為:

.table {
  width: 100%;
  border: 1px solid #C9C9C9;
  overflow-y: auto;
  box-sizing: border-box;
}

這樣,我們在計算 width 的時候,就會包含 border 的寬度,而不會出現不知名的滾動條了。

小結

box-sizing 其實是一個簡單的設置而已,但是這個屬性在對 CSS 不熟的階段會很容易被忽略,因為他不像是 background-color, color 這種屬性,設置了之後會有明顯的顏色改變,而且從名稱上來看也很容易理解。看到 box-sizing 的第一眼,其實我們也不太知道他是作什麼用的,但事實上,他在我們 Box Model 當中非常的重要,可以說是決定基準的角色,為什麼有人可以切版做到 pixel perfect,新手就不行?其實有時候就差在這一個簡單的觀念而已,只要掌握他,你也可以做到 pixel perfect。


上一篇
【Day16】滾動條 - 避免滾動穿透
下一篇
【Day18】盒子模型 - 邊距重疊
系列文
防禦性 CSS - 建立「防患未然」的匠人心態30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言