# Box Model

所有元素在 CSS 裡都有一個稱為「box」的機制影響著元素所佔區域範圍，下圖為一個 box 內的特性：

<figure><img src="https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/The_box_model/box-model.png" alt=""><figcaption></figcaption></figure>

{% embed url="<https://codepen.io/neillin1023/pen/jOKGZQw>" %}
透過範例觀察
{% endembed %}

下圖為 Chrome 瀏覽器的 Devtool 描繪出的數值：

<figure><img src="https://3433349642-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfNa3cQXA0JgS2aeBbzYg%2Fuploads%2FNMNbYkolSBxab0rdDjno%2F%E6%88%AA%E5%9C%96%202023-02-17%20%E4%B8%8A%E5%8D%889.52.52.png?alt=media&#x26;token=db807318-decb-48d7-bbb5-aade521662b0" alt=""><figcaption><p>你可以在開發者工具中，查看box model</p></figcaption></figure>

<figure><img src="https://3433349642-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfNa3cQXA0JgS2aeBbzYg%2Fuploads%2FUN9IhkbFmKFA021FfBSI%2F%E6%88%AA%E5%9C%96%202022-11-17%20%E4%B8%8B%E5%8D%881.31.31.png?alt=media&#x26;token=01f74dab-16b3-4fbf-ab76-b3db9c95e632" alt=""><figcaption><p>你可以在開發者工具中，查看box model</p></figcaption></figure>

{% hint style="info" %}
有發現到總寬不是 300px 嗎？
{% endhint %}

雖然我們的寬高設置了 300px 與 100px，但在預設的模式下，其實該區塊實際佔據的寬是 300+10\*2+5\*2=330，高為 100+10\*2+5\*2=130。

換句話說，在我們設置了寬度後，padding 與 border 的預設行為是**擴張此盒子**，而外面的 margin 則是將我們把 border 以外的東西推移開來。

但有時候實務上，我們可以想要從不同觀點出發，先確定寬高是多少後，才去決定 padding、border 是多少，這個可以使用 `box-sizing` 這個屬性調整模式：

{% embed url="<https://codepen.io/neillin1023/pen/yLEzvrp>" %}

<figure><img src="https://3433349642-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfNa3cQXA0JgS2aeBbzYg%2Fuploads%2FPfBbl8lGgwXVQsDWRl1X%2F%E6%88%AA%E5%9C%96%202022-11-17%20%E4%B8%8B%E5%8D%881.42.57.png?alt=media&#x26;token=b6c92f5d-8487-4a59-b8ad-c7902427633e" alt=""><figcaption><p>你可以在開發者工具中，查看box model</p></figcaption></figure>

可以看到，在最裡面的 content 寬高只剩下 270px 與 70px，也就是說在 border-box 這個模式下，總寬高的數值是已經包含 padding 和 border 所佔的區域。而預設的模式則稱之為 content-box。

接著在範例中，您有沒有觀察到為什麼「outside」的文字為什麼是在下方？而不是緊接在後呢？後面不是還有空位嗎？這個還牽扯到 box 有不同機制：

* **block box**
  * 特性為佔據整個寬度（通常意味著會換行）
  * 可以設置寬高
  * padding、margin、border 會將周圍推開
* **inline box**：
  * 不會換行
  * 無法設置寬高
  * padding、margin、border 會將周圍推開，但是...
    * 垂直方向「不會」把其他有 inline 的元素推開
    * 水平方向「會」把其他有 inline 的元素推開
* **inline-block box**：
  * 不會換行
  * 可以設置寬高
  * padding、margin、border 會將周圍推開

在這個範例中，因為我們使用的 `<div>` 是 block box，所以即便我們設置了寬高，但還是會佔據一整個寬度、會換行，所以文字才會出現在下方。

如果我們想要強制讓 `<div>` 改變機制，則可以使用 `display` 屬性來達成，例如改成 inline：

{% embed url="<https://codepen.io/neillin1023/pen/mdKBxbe>" %}

與之前的範例相比，寬度的設定已經無效，垂直方向的內外距、邊界也都不會推開，文字緊跟在後。

若改成 inline-block 的話，我們將會看到完整的內外距與邊界，如下：

{% embed url="<https://codepen.io/neillin1023/pen/YzvraXP>" %}

### 小結

暸解了盒子模型的概念後，之後每次使用 html 標籤時，都請好好的暸解預設是什麼情況。

### 作業

請試著玩看看以下這些 HTML 標籤的盒子模型是如何運作的，這些都是實務上很常用到的標籤：

* \<span>
* \<p>
* \<a>
* \<div>
* \<header>
* \<footer>
* \<main>
* \<nav>
* \<aside>
* \<section>
* \<img>

### 參考連結

* [Box Model](https://developer.mozilla.org/zh-CN/docs/Learn/CSS/Building_blocks/The_box_model)
