Pular para o conteúdo
Cursos

DevClub

LógicaFront-endBack-endMobile

IA Club

IA na prática
Estudar programaçãoEstudar IA
LiçãoIniciantecódigo testado

Box model CSS: controle o tamanho real dos elementos

Entenda content, padding, border e margin, compare content-box com border-box e corrija um cartão que transborda com medidas reais do navegador.

Rodolfo Mori5 min de leitura

O box model explica por que um elemento com width: 320px pode aparecer com 376 pixels de largura. Ele divide cada caixa em conteúdo, padding, border e margin, e permite calcular o tamanho antes que a página ganhe rolagem horizontal.

Vamos medir dois cartões da Livraria Beira-Rio no Google Chrome 151.0.7922.170. A primeira lição da trilha mostrou como os seletores levam uma regra até o elemento; agora a pergunta muda: depois que a regra chegou, quanto espaço esse elemento realmente ocupa?

Uma encomenda tem produto, proteção, caixa e distância

Pense em um livro enviado pelo correio. O livro é o content; o plástico-bolha ao redor é o padding; o papelão que delimita o pacote é o border; e o espaço deixado entre essa encomenda e as outras na prateleira é o margin. Essa é a ordem do centro para fora.

O mapeamento ajuda a localizar cada camada: conteúdo carrega texto ou imagem, padding cria respiro interno, border desenha o limite e margin afasta caixas vizinhas. Mas a comparação física acaba aí. Margens verticais de caixas CSS podem colapsar, e uma caixa pode sobrepor outra ou sair do fluxo; pacotes reais não seguem essas regras do navegador.

Este é o cartão que vamos medir:

html
<article class="caixa content-box" id="caixa-content">
  O Cortiço
</article>

As quatro camadas recebem valores explícitos para não depender do estilo padrão do navegador:

css
.caixa {
  width: 320px;
  padding: 24px;
  border: 4px solid rgb(37 99 235);
  margin: 16px;
}

.content-box {
  box-sizing: content-box;
}

box-sizing: content-box é o modelo padrão. Nesse modelo, width define apenas a área de conteúdo. O navegador soma 24 pixels de padding e 4 de borda em cada lado: 320 + 24 + 24 + 4 + 4 = 376.

Use offsetWidth para ler conteúdo, padding e border juntos. Em seguida, some as margens calculadas para descobrir o espaço horizontal reservado ao redor da caixa:

js
const caixa = document.querySelector('#caixa-content');
const estilo = getComputedStyle(caixa);

const espacoComMargens =
  caixa.offsetWidth +
  Number.parseFloat(estilo.marginLeft) +
  Number.parseFloat(estilo.marginRight);

console.log('width no CSS:', estilo.width);
console.log('caixa até a borda:', caixa.offsetWidth);
console.log('caixa com margens:', espacoComMargens);
width no CSS: 320px caixa até a borda: 376 caixa com margens: 408

O resultado separa três perguntas que costumam ser misturadas. width vale 320; a caixa visível até a borda vale 376; e o espaço horizontal considerando as duas margens vale 408. offsetWidth não inclui margin porque a margem está fora da borda.

Padding não é margin com outro nome

Os dois criam espaço, mas em lugares e com efeitos diferentes. padding fica dentro da borda, recebe o fundo do elemento e aumenta a área clicável de um botão. margin fica fora da borda, é transparente e separa aquela caixa das vizinhas.

Se um botão parece apertado por dentro, ajuste padding. Se dois cartões estão colados um no outro, ajuste o espaço entre eles — margin pode resolver em fluxo normal, enquanto gap costuma expressar melhor o espaço em Flexbox e Grid. A propriedade certa comunica a intenção para quem mantiver o código.

As formas abreviadas seguem o sentido de um relógio:

css
.produto-card {
  /* cima | direita | baixo | esquerda */
  padding: 12px 20px 16px 20px;

  /* vertical | horizontal */
  margin: 24px 16px;
}

Quando há quatro valores, leia a partir de cima e gire no sentido horário. Com dois, o primeiro vale para cima e baixo; o segundo vale para esquerda e direita. No início, escrever padding-top ou margin-inline pode ser mais claro que tentar lembrar uma abreviação no meio de uma depuração.

Border-box coloca a proteção dentro da medida

No modelo alternativo, ativado por box-sizing: border-box, o número em width representa a caixa até a borda. Padding e border continuam existindo, mas o navegador desconta essas partes da área de conteúdo.

css
.border-box {
  box-sizing: border-box;
  width: 320px;
  padding: 24px;
  border: 4px solid rgb(37 99 235);
  margin: 16px;
}

Coloque uma caixa content-box e outra border-box lado a lado no código e rode a mesma medição:

js
for (const seletor of ['#caixa-content', '#caixa-border']) {
  const elemento = document.querySelector(seletor);
  const estilo = getComputedStyle(elemento);
  const conteudo = elemento.clientWidth - 48; // padding: 24px em cada lado

  console.log(seletor, {
    width: estilo.width,
    offsetWidth: elemento.offsetWidth,
    conteudo,
  });
}
#caixa-content { width: '320px', offsetWidth: 376, conteudo: 320 } #caixa-border { width: '320px', offsetWidth: 320, conteudo: 264 }

O cartão border-box manteve os 320 pixels visíveis. Sua área de conteúdo ficou com 264: 320 - 48 de padding e - 8 de border. Não houve desaparecimento de espaço; houve uma mudança em qual camada o width mede.

Uma base comum de projeto ativa esse cálculo para todos os elementos, incluindo pseudo-elementos:

css
html {
  box-sizing: border-box;
}

*,
*::before,
*::after {
  box-sizing: inherit;
}

A herança deixa a decisão centralizada e ainda permite que uma região troque o modelo de propósito. Não copie o reset como encantamento: ele existe para que “320 pixels” signifique a largura até a borda na maior parte da interface.

O transbordamento que nasce de uma conta incompleta

Agora reproduza o defeito. Um contêiner oferece 340 pixels. O cartão pede 320, mas usa content-box com 24 pixels de padding e 4 de border em cada lado:

css
.limite {
  width: 340px;
  overflow: auto;
}

.estouro {
  box-sizing: content-box;
  width: 320px;
  padding: 24px;
  border: 4px solid rgb(185 28 28);
}

O width isolado parece caber: 320 é menor que 340. A caixa final não cabe, porque mede 376. O navegador comprovou o excesso comparando a largura interna do contêiner com a área que pode ser rolada:

js
const limite = document.querySelector('.limite');
const estouro = document.querySelector('.estouro');

console.log('contêiner:', limite.clientWidth);
console.log('cartão:', estouro.offsetWidth);
console.log('área rolável:', limite.scrollWidth);
console.log('excesso:', limite.scrollWidth - limite.clientWidth);
contêiner: 340 cartão: 376 área rolável: 376 excesso: 36

Uma rolagem horizontal de 36 pixels não é “o CSS ficando maluco”. É a soma correta de uma declaração que mediu só o conteúdo. Corrija a intenção dizendo que o cartão deve ocupar toda a largura disponível até a borda:

css
.estouro {
  box-sizing: border-box;
  width: 100%;
  padding: 24px;
  border: 4px solid rgb(185 28 28);
}
contêiner: 340 cartão: 340 área rolável: 340 excesso: 0

No mesmo teste, mudar apenas box-sizing e width eliminou o excesso. Evite esconder o sintoma com overflow-x: hidden no body; isso corta conteúdo sem corrigir a caixa que calculou mal o espaço.

Eixos lógicos deixam a caixa acompanhar o texto

margin-left fala de um lado físico. margin-inline-start fala do começo da linha, que pode mudar conforme a direção da escrita. Para interfaces que podem ser traduzidas, propriedades lógicas tornam a intenção mais resistente:

css
.produto-card {
  padding-block: 16px;
  padding-inline: 24px;
  margin-block-end: 20px;
  border-inline-start: 4px solid currentColor;
}

Em português, inline normalmente corresponde ao eixo horizontal e block ao vertical. A tradução prática é “respiro no sentido da linha” e “espaço no sentido dos blocos”, não uma promessa eterna de esquerda e direita.

Sua missão: medir antes e depois

Crie um cupom com largura de 280 pixels, padding de 20 pixels e border de 2 pixels. Comece com content-box, registre offsetWidth, troque para border-box e registre novamente.

html
<aside class="cupom" id="cupom">
  Use o código LEITURA10
</aside>
css
.cupom {
  box-sizing: content-box;
  width: 280px;
  padding: 20px;
  border: 2px dashed currentColor;
}

Seu critério de sucesso é prever os dois resultados sem abrir o console e depois confirmá-los: 324 pixels no primeiro modelo e 280 no segundo. Acrescente uma margem de 12 pixels em cada lado e explique por que offsetWidth não muda, embora a caixa precise de mais espaço no layout.

Com o tamanho de cada caixa sob controle, o próximo desafio é distribuir várias delas numa linha. É justamente o papel de Flexbox no CSS. Se uma regra do box model aparece riscada no DevTools, volte à cascata e aos seletores e siga, quando necessário, para especificidade.

  • css
  • box-model
  • box-sizing
  • padding
  • margin

Perguntas frequentes

A propriedade width inclui padding e border?
Depende de box-sizing. Com content-box, o padrão, width mede só o conteúdo e padding e border são somados por fora. Com border-box, width inclui conteúdo, padding e border.
Margin faz parte da largura de um elemento?
Margin fica fora da borda e não entra em offsetWidth nem na largura definida por width. Ela ainda ocupa espaço ao redor da caixa no layout, e margens verticais de blocos podem colapsar em algumas situações.
Devo usar box-sizing border-box em todo projeto?
É uma base comum porque torna a largura declarada mais previsível. O reset com herança preserva a possibilidade de um componente escolher outro modelo quando isso for necessário.
Por que width 100% pode causar rolagem horizontal?
Com content-box, os 100% medem apenas o conteúdo. Padding e border são acrescentados depois, então a caixa visível pode passar da largura do contêiner. Border-box inclui essas partes dentro dos 100%.

Dúvidas e comentários

Travou em algum passo? Pergunte aqui — a equipe e outros alunos respondem.

Todo o código deste artigo foi executado em Google Chrome 151.0.7922.170, e as saídas exibidas são as reais — como produzimos este conteúdo.

Fontes consultadas

  1. MDN — CSS box model — developer.mozilla.org
  2. MDN — Introduction to the CSS box model — developer.mozilla.org
  3. MDN — box-sizing — developer.mozilla.org
  4. CSS Box Model Module Level 4 — W3C — w3.org

Continue por aqui