CSS / padding e margin: espaçamento, largura e margens colapsadas

No CSS, padding é o espaço entre o conteúdo e a borda, enquanto margin está fora da borda. Use padding para expandir o interior de um elemento, incluindo seu fundo, e margin para ajustar sua separação dos elementos ao redor. A largura resultante depende de box-sizing, e margens verticais elegíveis podem colapsar em vez de simplesmente se somarem.

Diferenças entre padding e margin

A caixa de um elemento consiste em conteúdo, padding, borda e margem, nessa ordem de dentro para fora. Seu plano de fundo normalmente se estende pelo padding, enquanto a margem é transparente. Aumentar o padding de um botão geralmente expande sua caixa de fundo e clicável; adicionar margem não torna esse espaço externo clicável.

Característica padding margin
Posição Entre o conteúdo e a borda Fora da borda
Cor de fundo comum Também é pintada no padding Transparente
Valores negativos Não permitido Permitido
auto Não permitido Permitido; resolvido de acordo com as regras de layout

Ambas as propriedades aceitam valores como px, rem e %, mas padding: auto e preenchimento negativo são inválidos. Para as propriedades de espaçamento físico de um modo de escrita horizontal comum, os valores percentuais referem-se à largura do bloco contêiner, incluindo valores de topo e fundo. Eles não são uma porcentagem de sua altura. Definições de modelo de caixa e espaçamento do W3C

Ler as direções da notação abreviada

Uma notação abreviada com quatro valores começa no topo e segue no sentido horário: direita, inferior, esquerda. Dois valores significam vertical e horizontal; três significam topo, horizontal, inferior. A mesma regra se aplica ao padding e à margem.

Exemplo Topo Direita Inferior Esquerda
padding: 10px 10px 10px 10px 10px
padding: 10px 20px 10px 20px 10px 20px
padding: 10px 20px 30px 10px 20px 30px 20px
padding: 10px 20px 30px 40px 10px 20px 30px 40px

Para um lado, use uma propriedade como padding-top ou margin-left. Uma declaração abreviada posterior padding ou margin pode sobrescrever valores de lado previamente declarados, então verifique a ordem das regras.

Verificar as larguras com um exemplo completo

Salve o código completo abaixo como spacing.html em UTF-8 e abra-o em um navegador. Não é preciso instalar bibliotecas nem usar um servidor. Alpha, Beta e as outras palavras são rótulos de comparação. Após a edição, salve e recarregue. Selecione cada .box nas ferramentas de desenvolvedor e inspecione seu diagrama do modelo de caixa ou estilos computados para verificar larguras e espaçamentos.

<!doctype html>
<html lang="pt">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Comparar padding e margin</title>
  <style>
    body { font-family: sans-serif; max-width: 640px; margin: 0 auto; padding: 16px; }
    h2 { font-size: 1.1rem; }
    .stage { padding: 12px; border: 1px dashed #777; overflow-x: auto; }
    .box { width: 200px; padding: 16px; border: 4px solid #17324d; margin: 24px; background: #dcefff; }
    .content-box { box-sizing: content-box; }
    .border-box { box-sizing: border-box; }
    .asymmetric { box-sizing: border-box; padding: 8px 16px 24px 32px; margin: 10px 20px 30px 40px; }
    .center { box-sizing: border-box; margin: 0 auto; }
    .collapse-demo { display: flow-root; border: 1px dashed #777; }
    .item { height: 30px; background: #dcefff; }
    .first { margin: 0 0 24px; }
    .second { margin: 16px 0 0; }
  </style>
</head>
<body>
  <h1>Comparar padding e margin</h1>
  <h2>content-box</h2>
  <div class="stage"><div class="box content-box">Alpha</div></div>
  <h2>border-box</h2>
  <div class="stage"><div class="box border-box">Beta</div></div>
  <h2>padding / margin</h2>
  <div class="stage"><div class="box asymmetric">Gamma</div></div>
  <h2>margin: 0 auto</h2>
  <div class="stage"><div class="box center">Delta</div></div>
  <h2>margin-bottom / margin-top</h2>
  <div class="collapse-demo">
    <div class="item first">A</div>
    <div class="item second">B</div>
  </div>
</body>
</html>

Alpha tem uma largura de border-box de 200 + 16 × 2 + 4 × 2 = 240px. Incluindo suas margens horizontais, ocupa 240 + 24 × 2 = 288px. Beta usa dimensionamento border-box, então sua largura de border-box é 200px e sua largura de conteúdo é 200 - 16 × 2 - 4 × 2 = 160px. Esses cálculos não incluem o padding e a borda do elemento stage ao redor.

Gamma tem 8px de padding na parte superior, 16px na direita, 24px na parte inferior e 32px na esquerda. Suas margens são 10px, 20px, 30px e 40px na mesma ordem. Compare as diferenças visíveis com as direções abreviadas acima.

Definir o cálculo do tamanho com box-sizing

Com content-box, a largura especifica a largura do conteúdo, com o preenchimento (padding) e a borda adicionados fora dela. Com border-box, a largura especificada inclui conteúdo, preenchimento e borda. Nenhum dos modos de dimensionamento inclui a margem na largura. Elementos div comuns inicialmente usam content-box, mas o CSS reset de um site pode alterar isso; inspecione o valor calculado.

Substitua a regra .content-box do exemplo pela seguinte. A largura do border-box de Alpha muda de 240px para 200px. Mantenha os outros valores inalterados, compare e restaure content-box. Se o preenchimento e a borda juntos excederem a largura especificada, a largura do conteúdo não pode se tornar negativa, então a caixa resultante ainda pode ser mais larga do que o esperado.

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

Explicação da MDN sobre box-sizing

Centralizar um bloco com margens automáticas

Para centralizar horizontalmente um bloco no fluxo normal, a caixa deve ser mais estreita que a largura disponível em seu elemento pai e suas margens esquerda e direita devem ser automáticas. Delta tem largura de 200px e margin: 0 auto, então o espaço horizontal restante é compartilhado entre ambos os lados. A centralização por si só não resolve o transbordamento quando o pai é muito estreito.

Se um bloco comum com largura automática já preenche o espaço horizontal disponível, adicionar margens laterais automáticas não produz efeito visível de centralização. No fluxo normal, margin-top: auto e margin-bottom: auto não o centralizam verticalmente. Margens automáticas no Flexbox ou Grid seguem regras de layout diferentes, portanto, distinga esses contextos.

Entender o colapso de margens e os valores negativos

As margens verticais adjacentes elegíveis podem colapsar no layout de bloco comum. No último exemplo, a margem inferior de 24px de A e a margem superior de 16px de B são ambas positivas, então o espaço entre elas é o valor maior, 24px, em vez de 40px. A borda do elemento pai impede o colapso de margens entre esse pai e seus filhos neste exemplo.

Altere a regra .collapse-demo do exemplo conforme abaixo. Seus filhos se tornam itens flex, cujas margens não colapsam entre si, então o espaço se torna 24 + 16 = 40px. Compare e restaure display: flow-root. Aplicar flow-root apenas a um elemento pai não elimina todo o colapso de margens entre blocos irmãos.

.collapse-demo {
  display: flex;
  flex-direction: column;
  border: 1px dashed #777;
}

No modo de escrita horizontal usado aqui, as margens esquerda e direita não colapsam dessa forma. Ao colapsar margens com valores positivos e negativos, some o maior valor positivo ao valor negativo de maior valor absoluto: 24px e -8px produzem 16px. Se todos os valores forem negativos, use o valor mais negativo; -8px e -16px produzem -16px. Uma declaração como margin-left: -8px é válida, mas pode causar sobreposição ou mover o conteúdo para fora de seu elemento pai. Verifique telas estreitas e indicadores de foco do teclado. Padding negativo não pode produzir o mesmo efeito. Regras de colapso de margem W3C

Investigar um espaçamento inesperado

  1. Verifique os padrões do navegador. A margem padrão do elemento body ou as margens verticais padrão de p e h1 podem fazer com que o espaçamento pareça maior do que suas declarações. Redefina os elementos relevantes em vez de remover cegamente todo o espaçamento.
  2. Para um elemento inline comum não substituído, como span, as margens verticais não afetam o layout da linha. O padding inline pode ser aplicado sem empurrar as linhas adjacentes como esperado. Considere inline-block ou outro modo de layout quando a caixa precisar de dimensionamento e espaçamento independentes.
  3. Use ferramentas de desenvolvedor para verificar se o seletor corresponde, a declaração é válida e se uma regra de maior prioridade ou uma abreviação posterior não a substituiu. Compare também em uma largura estreita, verificando o overflow e o efeito do padding na largura.

Para definir o espaçamento em relação à direção da escrita, use propriedades lógicas como padding-inline e margin-block. Na escrita horizontal comum, o eixo inline é horizontal e o eixo de bloco é vertical. Esses eixos mudam na escrita vertical, então eles nem sempre correspondem aos lados físicos esquerdo e direito.