CSS Box Model: corrigindo elementos com tamanhos inesperados
Tags: css, boxmodel, margin, padding
Published: 2022-07-13 00:04:54

## O Box Model define as 4 partes de um elemento HTML: conteúdo, padding, border e margin. Só isso seria simples, se não fosse o box-sizing interferindo no tamanho dos elementos. Para se aprofundar em front-end, é preciso entender também sobre o box-sizing e o impacto dele no funcionamento de width.
 
- Entenda de Box Model
- `padding` é o espaço entre o conteúdo do elemento e sua borda
- `margin` é a distância entre dois elementos
- A propriedade `width` muda seu comportamento dependendo do valor da propriedade `box-sizing`
- De preferência, sempre insira o trecho  `* { box-sizing: border-box; }` no CSS de todos os seus projetos
 
HTML é um monte de caixinha dentro de caixinha dentro de caixinha... (e contando).
 
E essas caixinhas são representadas pelo **Box Model**. Ele não é uma propriedade CSS, mas sim um conceito muito importante. Entender de Box Model pode evitar algumas dores de cabeça, enquanto você desenvolve seus sites.
 
![Box Model mostrando as medidas do conteúdo, padding, border e margin](https://www.datocms-assets.com/64896/1655653671-1.png)
 
Vou começar com uma dica bem simples, porém essencial antes de avançar para os próximos capítulos.
 
## Padding e Margin não são a mesma coisa
 
Agora pode parecer óbvio.
 
Mas no início dos meus estudos, eu achava que `padding` e `margin` eram praticamente a mesma coisa (chora Box Model).
 
Eu sempre pensava que o objetivo era o mesmo: criar um espaço entre os elementos:
 
```html
<button class="button--primary">
  OK
</button>

<button class="button--secondary">
  CANCEL
</button>
```
 
```css
.button--primary,
.button--secondary {
  border: none;
  background-color: transparent;
  padding: 0;
  margin: 0;
}

.button--primary {
  padding-right: 20px;
  margin-right: 20px;
}
```
 
Tanto o `padding` quanto o `margin` aplicados no `.button--primary` inserem um espaço entre os botões.
 
Veja o `padding` na cor verde e o `margin` na cor laranja:
 
![Dois botões com padding e margin entre eles. Os botões não possuem borda](https://www.datocms-assets.com/64896/1655653688-2.png)
 
Porém, quando adiciono uma borda nos botões, a diferença entre eles fica mais clara:
 
```css
.button--primary,
.button--secondary {
  border: 5px solid black; /* aqui */
  background-color: transparent;
  padding: 0;
  margin: 0;
}

.button--primary {
  padding-right: 20px;
  margin-right: 20px;
}
```
 
![Dois botões com padding e margin entre eles. Os botões possuem borda](https://www.datocms-assets.com/64896/1655653706-3.png)
 
**Pense no `padding` como uma alteração mais individual, já que ele adiciona um preenchimento entre o conteúdo *do elemento* e a borda *do elemento* (assim como um botox que preenche o lábio).**
 
**Por outro lado, o `margin` é mais usado quando você olha para o layout, uma vez que ele adiciona um espaço entre a borda e o elemento vizinho (ou o canto da janela). É como se fosse o distanciamento social que as pessoas deveriam ter feito na pandemia.**
 
Após compreender essas duas propriedades, fica mais fácil entender o que é o **Box Model** (e a importância dele).
 
## Box Model
 
![Imagem ilustrativa de um Box Model](https://www.datocms-assets.com/64896/1655653671-1.png)
 
Pense que cada elemento HTML é uma caixa que possui:
 
- **Conteúdo (azul):** texto, imagem, vídeo ou outro elemento HTML
- **Padding (verde):** preenchimento entre o conteúdo e a borda
- **Borda (amarela):** controlada pela propriedade `border` do CSS
- **Margin (laranja):** distância entre o elemento analisado e seu vizinho
 
Entender o **Box Model** pode facilitar muito a sua vida e te ajudar a desenvolver sites com menos dores de cabeça.
 
Então para saber o tamanho de um elemento basta somar o seu conteúdo, padding, borda e margin, certo? Bem, nem sempre.
 
## Box-sizing e seu impacto no Box Model
 
O tamanho de cada caixinha (definido em `width`)depende da propriedade `box-sizing`.
 
[Segundo a W3C](https://www.w3schools.com/cssref/css3_pr_box-sizing.asp), Ela possui dois valores:
 
1. **Content-box**: o tamanho da caixa é o resultado de `width` + `padding` + `margin`
2. **Border-box**: o tamanho da caixa é definido apenas pela propriedade `width`
 
Veja um exercício básico. Qual será a largura dessa `div`, dado que seu conteúdo tem largura de 50px?
 
```css
div {
  display: inline-block;
  padding: 30px;
  border: 5px solid black;
}
```
 
O cálculo é feito da seguinte forma:
 
conteúdo + padding-left + padding-right + border-left + border-right
 
Ou seja
 
50 + 30 + 30 + 5 + 5 = **120px**
 
Agora, algo estranho acontece quando acrescento a propriedade `width`:
 
```css
div {
  display: inline-block;
  padding: 30px;
  border: 5px solid black;
  width: 300px; /* plim */
}
```
 
Qual será a nova largura:
 
- 120px?
- 300px?
- 370px?
 
Estranhamente, o Box Model define que será 370px, e isso é responsabilidade da propriedade `box-sizing`, pois por padrão ela possui o valor `content-box`.
 
Assim, a linha `width: 300px` irá modificar a largura do *conteúdo*. Mas falta somar o `padding` e `border` ao seu tamanho total.
 
conteúdo + padding-left + padding-right + border-left + border-right
 
Ou seja
 
300 + 30 + 30 + 5 + 5 = **370px**
 
Isso causa uma grande confusão, já que o elemento não tem 300px de largura, apesar de isso estar explícito no CSS. 
 
A forma de resolver isso é com esse trecho de código que é quase um mantra entre os front-ends:
 
```css
* {
  box-sizing: border-box;
}
```
 
Isso altera a propriedade `box-sizing` de todos os elementos para o valor `border-box`.
 
**A partir de agora, o navegador irá incluir padding e borda no valor da propriedade `width`, e no caso irá totalizar sempre os 300px.**
 
Todos os cálculos foram feitos sem somar o tamanho das margens. Ela é válida para fins de layout, mas o navegador não considera ela no cálculo do tamanho total.
 
## Callback
 
Defina o quanto antes no seu projeto o `* { box-sizing: border-box; }`, para não ter problema no tamanho dos elementos.
 
E não se esqueça de comentar aqui abaixo, caso essa propriedade (ou a falta dela) já tenha te dado problemas.
 
Obrigado pela sua leitura, e até a próxima :)