CSS: Aprendendo box model com analogias
Tags: css, learning, beginners, braziliandevs
Published: 2024-07-05 14:50:09

## Introdução
Se você está estudando CSS, talvez já tenha se deparado com o termo _box model_. Caso ainda não tenha, não se preocupe, iremos abordar esse assunto nesse artigo.

Basicamente todo elemento em uma página web é um retângulo chamado de _box_ (caixa), e daí vem o nome _box model_ ou _modelo de caixa_. Entendermos como funciona esse modelo é a base para conseguirmos criar layouts mais complexos com CSS, ou alinhar itens corretamente.

![Meme GIF CSS - Peter Griffin de Family Guy tentando arrumar uma persiana](https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExZXdoa2wwOXAyNHcwa2F5MmI4dHcxa3AwYnRpc2pyaTJsMzR3cjFydiZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/13FrpeVH09Zrb2/giphy.gif)

Ao inspecionar um elemento (clicando com o botão direito ou abrindo o **DevTools** com os atalhos Ctrl+Shift+C ou F12, dependendo do seu navegador), na aba _Computed_ (Calculado), você provavelmente irá ver a imagem a seguir:

<figure>
  <a id="computed"></a>
  ![Print da aba 'calculado' do DevTools](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kf8uwcl1pijc24a2s5qv.png)
  <figcaption>Fig.1 - Propriedades do elemento (aba _Computed_)</figcaption>
</figure>

No próximo tópico iremos ver detalhadamente o que significa cada parte dessa imagem.

## Estrutura básica do **box model**
Para ilustrar a estrutura básica do _box model_ irei utilizar como exemplo a construção de uma casa em um terreno. Essa ideia foi inspirada neste artigo [[1]][Ref1] (em inglês).

As partes que compõem a estrutura do _box model_ são:

### **Conteúdo** (_Content_)

O conteúdo se refere à parte mais central da [Fig.1][Fig1] em azul, e está relacionado ao conteúdo dentro de uma tag HTML, como por exemplo o texto em um parágrafo (**`<p>`**).

O conteúdo é composto basicamente por duas propriedades, largura (`width`) e altura (`height`).

No nosso exemplo, o conteúdo será a casinha abaixo ([Fig.2][Fig2]) (se você inspecionar a imagem da casa, verá que as medidas são as mesmas da [Fig.1][Fig1]). As dimensões da casa são 81px de largura e 93 px de altura.

<figure>
  <a id="casa"></a>
  ![Casa feita em pixel art](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/04qnyrtcsnvy9dhtxpr3.png)
  <figcaption>Fig. 2 - Conteúdo (casa) e suas dimensões</figcaption>
</figure>

O conteúdo precisa estar dentro de uma estrutura HTML, portanto colocaremos nossa casinha dentro de um lote para representar esta estrutura:

<figure>
  <a id="casa-lote"></a>
  ![Casa posicionada no centro do lote](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s35or8xhu0dgqlf96hql.png)
  <figcaption>Fig. 3 - Casa posicionada no centro do lote</figcaption>
</figure>

### **Preenchimento** (_Padding_)
A parte em verde da [Fig.1][Fig1] é a propriedade chamada de `padding` (preenchimento), que cria um espaço ao redor do conteúdo.

O `padding` é demonstrado pela parte de terra, onde será o jardim, por exemplo:

<figure>
  <a id="padding"></a>
  ![Padding adicionado ao lote como uma área de terra ao redor da casa](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n9mqclmz37kqdgbi7wq3.png)
  <figcaption>Fig. 4 - Padding adicionado como uma área de terra ao redor da casa</figcaption>
</figure>

### **Borda** (_Border_)
A seguir temos a propriedade `border`, ou borda, que é responsável por delimitar nosso conteúdo e está representada pela cor amarela na [Fig.1][Fig1]. A borda é a última propriedade do nosso elemento que pode ser vista.

A borda pode ser representada como o muro ou, no nosso caso, a cerca da casa:

<figure>
  <a id="margin"></a>
  ![Border (Cerca) adicionada ao redor do padding](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9jz6dnyxrche2h91ublv.png)
  <figcaption>Fig. 5 - Border (Cerca) adicionada ao redor do padding</figcaption>
</figure>

### **Margem** (_Margin_)
Por fim, temos a propriedade `margin`, em laranja ([Fig.1][Fig1]), que inclui uma área vazia ao redor do nosso elemento. Como pode ser visto na imagem:

<figure>
  <a id="margin"></a>
  ![Margem adicionada ao elemento, criando uma área vazia ao redor da borda](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bb2tbrnugafdsga9thn5.png)
  <figcaption>Fig. 6 - Margem adicionada ao elemento, criando uma área vazia ao redor da borda</figcaption>
</figure>

Neste caso, reduzimos o `padding` para que a margem pudesse ser representada na imagem.

## A propriedade **`box-sizing`**

Agora que conhecemos a estrutura do _box model_, podemos abordar a propriedade `box-sizing`. Essa propriedade nos permite dizer ao navegador como ele deve calcular a altura e a largura do elemento. Temos apenas 2 valores possíveis:

### content-box
Este é o valor padrão, em que a altura e a largura do elemento incluem apenas o conteúdo. Portanto, se tivermos um conteúdo com `height`(altura) e `width`(largura) de 100px, mais 10px de `padding`, mais 5px de `border` e 5 de `margin`, veremos que o tamanho do nosso elemento mudou de 100px para 130px:

<figure>
  <a id="content-box-example"></a>
  ![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tsf578lm7q1mnhmeqb4e.png)
  <figcaption>Fig. 7 - Div com 100 px de altura e largura, 10px de padding, 5px de border e 5px de margin utilizando o valor padrão `content-box`</figcaption>
</figure>

Veja o código aqui:
{% codepen https://codepen.io/fhmurakami/pen/QWXLdpX %}

Isso ocorre pois as propriedades _`height`_ e _`width`_, são aplicadas somente ao conteúdo (a parte azul da [Fig.1][Fig1], lembra?). Porém adicionamos ainda o `padding`, a `border` e a `margin`:

100px (`height`/`width`) + 2 * 10px (`padding`) + 2 * 5px (`border`) + 2 * 5px (`margin`) = **140px**

> #### **Atenção!** :warning:
> Ué?! :thinking:
>
> A imagem mostra o elemento com 130px e não 140px!
> Exato! Lembre-se que a `margin` é uma propriedade externa (ou um espaço vazio em volta) do elemento e por isso não deve ser somada à altura e à largura do mesmo.

Podemos pensar que com a propriedade `box-sizing` com o valor `content-box`, nosso elemento vai crescendo conforme adicionamos mais "camadas".
Para explicar, utilizarei mais uma analogia: Imagine um balão, daqueles de festa de criança, com doces dentro.

<center>
  <table>
    <tr>
      <td>
        <figure>
          <a id="baloon"></a>
          <img alt="Balão onde iremos colocar os doces" src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jx739awww0jowwoonp8o.png" />
          <figcaption>Fig. 8 - Balão de festa (<code>border</code>)</figcaption>
        </figure>
      </td>
      <td>
        <figure>
          <a id="candies"></a>
          <img alt="Doces" src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/15qcojcdwti9cpc9ops0.png" />
          <figcaption>Fig. 9 - Doces (<code>content</code>)</figcaption>
        </figure>
      </td>
    </tr>
    <tr>
      <td colspan="2">
        <figure>
          <a id="baloon-candies"></a>
          <img alt="Balão cortado para exibir os doces dentro" src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/23d4459r9hpc24dinodj.png" />
          <figcaption>Fig. 10 - Balão com os doces dentro</figcaption>
        </figure>
      </td>
    </tr>
  </table>
</center>

Os doces serão o nosso conteúdo, com uma altura e largura fixos. Para que seja possível estourar o balão, vamos adicionar um `padding` (ar) dentro do balão. O balão em si, é a `border` e a `margin` é todo o espaço em volta do balão:

<figure>
  <a id="baloon-full"></a>
  <img alt="Balão pendurado no teto com espaço vazio ao seu redor" src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/huhrywjs718o6twheanr.png" />
  <figcaption>Fig. 11 - Doces (<code>content</code>), ar (<code>padding</code>), balão (<code>border</code>), espaço em volta do balão (<code>margin</code>)</figcaption>
</figure>

Viu como nosso elemento foi crescendo conforme adicionamos mais propriedades? Ou se adicionarmos mais ar (`padding`) ao balão?

Outro exemplo de `content-box` utilizando analogia: um saco de pipoca no microondas, onde temos inicialmente o `content` (milho), a `border` (saco de papel) e `margin` (espaço interno do microondas). Porém ao aquecer, lentamente um `padding`(ar/vapor dentro do saco) vai sendo adicionado.

### border-box
O outro valor possível para a propriedade `box-sizing` é o `border-box`. Ele é muito útil quando você quer ter certeza do espaço que seu elemento irá ocupar na página, pois ao invés de atribuir a altura e a largura apenas ao conteúdo, ele utiliza o elemento todo (`content + padding + border`). Isso ajuda na criação de layouts responsivos, pois garantimos os elementos terão o tamanho exato que for definido mesmo utilizando medidas relativas (`%`, `em`, `rem` etc.).

Utilizando o mesmo exemplo da [Fig.7][Fig7], porém adicionando a propriedade `box-sizing: border-box;` teremos um elemento final com os 100px de altura e largura como definimos anteriormente.

<figure>
  <a id="border-box-example"></a>
  <img alt="Div com 100 px de altura e largura, 10px de padding, 5px de border e 5px de margin, porém desta vez utilizando o valor border-box" src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ga0e6zyju1aqknvc71vy.png"/>
  <figcaption> Fig. 12 - Div com 100 px de altura e largura, 10px de padding, 5px de border e 5px de margin, porém desta vez utilizando o valor <code>border-box</code> </figcaption>
</figure>

A diferença é que agora nosso conteúdo reduziu para 70px de altura e largura para não ultrapassar os 100px no total.

<figure>
  <a id="computed-border-box"></a>
  <img alt="Imagem da aba computed mostrando que o conteúdo foi reduzido para 70px de altura e largura" src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gn7pkcr45w7nup242uoi.png" />
  <figcaption> Fig. 13 - Aba <code>computed</code> ao inspecionar o elemento </figcaption>
</figure>

Vejo o código aqui:
{% codepen https://codepen.io/fhmurakami/pen/wvLwggR %}

Neste caso, devemos pensar em algo em que as medidas finais não possam ultrapassar um determinado tamanho. Para isso utilizaremos uma caixa térmica como o tamanho máximo, sendo assim, a caixa representará a `borda` do nosso elemento:

<figure>
  <a id="cooler-vazio"></a>
  ![Caixa térmica vermelha com borda branca e sem tampa](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m9whp64mx7skktnnryns.png)
  <figcaption>
    Fig. 14 - Caixa térmica (`border`)
  </figcaption>
</figure>

O `conteúdo` será a bebida que queremos gelar, e o gelo é o `padding`:

<center>
  <table>
    <tr>
      <td>
        <figure>
          <a id="barril-chopp"></a>
          <img alt="Barril de chopp" src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rq41pe25twoxpbzli7g2.png" />
          <figcaption>Fig. 15 - Barril de chopp (<code>content</code>)</figcaption>
        </figure>
      </td>
      <td>
        <figure>
          <a id="gelo"></a>
          <img alt="Cubos de gelo" src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3soshxk0pfw00i2iju2a.png" />
          <figcaption>Fig. 16 - Cubos de gelo (<code>padding</code>)</figcaption>
        </figure>
      </td>
    </tr>
    <tr>
      <td colspan="2">
        <figure>
          <a id="cooler-cheio"></a>
          <img alt="Caixa térmica com a bebida e o gelo" src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7rpvts1fh4n098sntuw7.png" />
          <figcaption>Fig. 17 - Caixa térmica com a bebida e o gelo</figcaption>
        </figure>
      </td>
    </tr>
  </table>
</center>

Perceba que quanto mais gelo colocarmos, menor será a bebida que conseguiremos gelar. Como não podemos ter um conteúdo com medidas negativas, o menor tamanho possível será de 0px. Porém, supondo que nossa caixa tenha 100px de `altura` por 120px de `largura` , e definirmos um `padding` de 60px, ao todo teremos 120px de gelo tanto na horizontal quanto na vertical, ou seja, o gelo irá transbordar a caixa térmica. 

<figure>
  <a id="padding-overflow"></a>
  ![Caixa térmica vermelha com gelo ultrapassando a altura máxima da caixa](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7v4qnxgw0piducwagqdl.png)
  <figcaption>
    Fig. 18 - Gelo transbordando a o limite máximo (altura) da caixa térmica
  </figcaption>
</figure>

O mesmo acontece com nosso elemento HTML:
<figure>
  <a id="border-box-overflow"></a>
  ![Imagem da aba computed mostrando que o conteúdo foi reduzido para 0px de altura e largura, mas a altura total do elemento aumentou para 150px](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5uzc82a908v1a80mhoe3.png)
  <figcaption>
    Fig. 19 - Inspecionando o elemento é possível ver que, ao adicionar um padding maior do que o tamanho total do elemento, o conteúdo foi reduzido para 0x0 px e a altura aumentou para 150px, mesmo com o `box-sizing: border-box`
  </figcaption>
</figure>

Vejo o código aqui:
{% codepen https://codepen.io/fhmurakami/pen/mdZbJZp %}

## Conclusão
Agora que você já conhece a estrutura básica do _Box Model_, e a propriedade `box-sizing`, ficará mais fácil entender como os elementos se comportam na sua página web e saber quando usar cada um dos valores (`content-box` e `border-box`). Se você inspecionar os elementos dos sites que utiliza no dia-a-dia, verá que a maioria utiliza `border-box` para seus elementos, pois essa propriedade tem facilitado muito o design responsivo. :)

Parabéns por ter chegado até aqui!

![Canecas de cerveja brindando](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lsjnxtd5bpk1hyen7iqq.png)

Ficou com alguma dúvida? Tem alguma sugestão? Fique a vontade para deixar seu comentário, ou se preferir, mande uma mensagem privada no [Linkedin](https://www.linkedin.com/in/felipe-murakami/).

> ### **Observação** ❗🚫
> Todas as imagens deste artigo foram feitas por mim, favor não utilizá-las sem o devido consentimento/crédito.
> Os assets prontos que utilizei estão nas referências, e o uso para projetos não-comerciais é permitido.

## Referências
<a id="ref1"></a>[1] [The CSS Box Model Explained by Living in a Boring Suburban Neighborhood](https://blog.codeanalogies.com/2017/03/27/the-css-box-model-explained-by-living-in-a-boring-suburban-neighborhood/)
<a id="ref2"></a>[2] [MDN Web Docs - The box model](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/The_box_model)
<a id="ref3"></a>[3] [MDN Web Docs - Introduction to the CSS basic box model](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_box_model/Introduction_to_the_CSS_box_model)
<a id="ref4"></a>[4] [MDN Web Docs - box-sizing](https://developer.mozilla.org/en-US/docs/Web/CSS/box-sizing)
<a id="ref5"></a>[5] [W3Schools - CSS Box Model](https://www.w3schools.com/css/css_boxmodel.asp)
<a id="ref6"></a>[6] [W3Schools - CSS Box Sizing](https://www.w3schools.com/css/css3_box-sizing.asp)
<a id="ref7"></a>[7] [The Odin Project - Foundations Course - The Box Model](https://www.theodinproject.com/lessons/foundations-the-box-model#introduction)
<a id="ref8"></a>[8] [Learn CSS BOX MODEL - With Real World Examples](https://www.youtube.com/watch?v=nSst4-WbEZk)
<a id="ref9"></a>[9] [Learn CSS Box Model in 8 minutes](https://www.youtube.com/watch?v=rIO5326FgPEhttps://www.youtube.com/watch?v=rIO5326FgPE)
<a id="ref10"></a>[10] [box-sizing: border-box (EASY!)](https://www.youtube.com/watch?v=HdZHcFWcAd8)
<a id="ref11"></a>[11] [Assets utilizados nas imagens para os exemplos de Box Model](https://butterymilk.itch.io/tiny-wonder-farm-asset-pack)
<a id="ref12"></a>[12] [Assets - Caneca de cerveja](https://henrysoftware.itch.io/godot-pixel-food)

[Fig1]: #computed
[Fig2]: #casa
[Fig3]: #casa-lote
[Fig4]: #padding
[Fig5]: #border
[Fig6]: #margin
[Fig7]: #content-box-example
[Fig8]: #baloon
[Fig9]: #candies
[Fig10]: #baloon-candies
[Fig11]: #baloon-full
[Fig12]: #border-box-example
[Fig13]: #computed-border-box
[Fig14]: #cooler-vazio
[Fig15]: #barril-chopp
[Fig16]: #border-box-overflow
[Fig17]: #cooler-cheio
[Fig18]: #padding-overflow
[Fig19]: #border-box-overflow

[Ref1]: #ref1