Boas práticas para evitar problemas com margin collapsing em CSS

O margin collapsing pode causar problemas em seu layout. Por sorte, o CSS já está preparado para resolver o seu design.

  • margin collapsing
  • margin
  • html
  • css
  • elemento
Front-end

Shortcut

As margens que se encostam, sem nada entre elas, se juntam em uma só e ocupam o mesmo espaço na tela.

Veja o conteúdo abaixo:

<p>Primeiro texto</p>
<p>Segundo texto</p>
p {
  margin-top: 10px;
  margin-bottom: 10px;
}

E agora responda: quantos pixels de espaçamento existem entre o primeiro e o segundo parágrafo:

  1. 0px

  2. 10px

  3. 20px

  4. Girafa

Se você respondeu 0px, largue as drogas.

Se respondeu 10px, já sabe do que vou falar. O que está fazendo aqui? Brincadeira, fica, vai ter bolo.

Se respondeu 20px, esse post é para você.

Agora, se respondeu girafa... tá tudo bem?

Assim como falei nesse post sobre box model, HTML é um monte de caixinhaa dentro de caixinha. Os componentes que formam elas são:

  • Conteúdo

  • Padding

  • Border

  • Margin

Se quiser entender melhor, revise alguns conceitos no post antes de prosseguir.


Agora vou falar sobre:

  • O que é o margin collapsing

  • As 3 situações onde ele acontece

  • Margin collapsing com mais de duas margens

  • Cálculo

  • Como corrigir

Agora que o box model está mais claro para você, eu começo com a definição da palavra.

O que é margin collapsing?

Antes de tudo, o que é margin?

Margin é uma das propriedades CSS que compõem o box model. O seu valor cria um espaçamento para os elementos próximos nas quatro direções: cima, direita, baixo, esquerda (parece golpe do Street Fighter).

Seu objetivo é criar um espaço entre ele e um elemento irmão. Margin não serve (ou não deveria servir) para separar um elemento filho de um pai.

Em alguns momentos, você vai encontrar algumas margens que se encostam, sem nada entre elas. Elas podem ser do mesmo elemento ou de elementos diferentes. Nesse momento, acontece o margin collapsing, que é quando as duas margens se sobrepõem e ocupam o mesmo espaço na tela.

É importante deixar claro que isso só acontece com margin-top e margin-bottom, e nunca com margin-left e margin-right.

Mas o margin collapsing não acontece sempre.

Quando o margin collapsing acontece

O margin collapsing acontece em 3 situações.

1. Elementos irmãos próximos

É o caso mais clássico.

Quando dois elementos irmãos são posicionados verticalmente, o margin-bottom do primeiro se junta com o margin-top do segundo.

margin-bottom de um elemento colidindo com o margin-top do próximo elemento
margin-topde um elemento colidindo com o margin-bottom do elemento anterior

2. Elemento pai com primeiro e último filho

Briga de família aqui.

margin-top e margin-bottom do elemento pai que envolve dois parágrafos

O margin collapsing acontece entre o margin-top do elemento pai e o margin-top do primeiro filho:

margin-top do elemento pai e primeiro filho colidindo

E entre o margin-bottom do elemento pai com o margin-bottom do último filho:

margin-bottom do elemento pai e último filho colidindo

Perceba que nesse caso, o collapsing acontece entre duas margens no mesmo sentido: para cima ou para baixo.

Caso a margem que se destaque seja do elemento filho (por exemplo, o segundo parágrafo), ela é "virtualmente" transferida ao pai (div-1). Assim, ele cria um espaço para seus irmãos (outras divs irmãs da div-1). Mas se olhar pelo devtools, ela permanece no filho.

3. Elemento vazio

Entende-se um elemento vazio como sem valor, logo ele praticamente some da tela.

Se um elemento HTML estiver vazio, o margin-top e margin-bottom dele se colapsam.

margin collapsing de um elemento vazio
elemento vazio sendo ignorado e sobreposto pelo próximo elemento

Perceba que é como se o terceiro parágrafo ignorasse a existência do segundo parágrafo, o vazio.


Entender as 3 situações onde o margin collapsing acontece, não é muito complicado. Porém agora você verá outros detalhes sobre esse fenômeno.

Margin collapsing com mais de duas margens

Preciso dizer que eu menti.

Você lembra que eu disse "o margin collapsing é quando duas margens se sobrepõem"? Não era bem verdade, pois mais de duas margens podem estar envolvidas em um collapsing.

Para isso, é necessário combinar 2 dos 3 casos que expliquei (ou todos eles):

<div class="div-1">
  <p>Texto</p>
</div>

<div class="div-2">
  <p>Texto</p>
</div>
.div-1 {
  margin-bottom: 5px;
}

.div-1 p {
  margin-bottom: 15px;
}

.div-2 {
  margin-top: 20px;
}

.div-2 p {
  margin-top: 10px;
}

Todas as margens que declarei acima, se sobrepõem, basta testar o código para confirmar.

E após toda essa salada de margins, é possível ver que o espaço final foi de 20px, exatamente o margin-top da div-2.

Mas como isso foi definido?

Como calcular o valor final de um margin collapsing

Quando duas ou mais margens se sobrepõem, o navegador calcula a margem final.

Apesar de saber que ele fará esse trabalho para você, é importante entender como esse cálculo é feito. Assim, você começa a se aprofundar nos conceitos de como o navegador e a web funcionam.

Margens positivas

Foi o caso do exemplo anterior.

Se duas ou mais margens positivas estiverem em um collapsing, o resultado final será a maior margem:

Margin collapsing com duas ou mais margens positivas
Margins envolvidas no collapsingMargin final
5px35px
35px
20px

Margem positiva com outra zerada

Nesse caso, segue a mesma regra anterior: permanece a maior margem, ou a única margem positiva:

Margin collapsing com uma ou mais margens positivas e a outra zerada
Margins envolvidas no collapsingMargin final
5px18px
18px
0

Margens negativas

Se apenas margens negativas estiverem envolvidas, o resultado final será a menor margem:

Margin collapsing com duas ou mais margens negativas
Margins envolvidas no collapsingMargin final
-5px-20px
-20px
-15px

Margin negativa com positiva

Quando houver margens de sinais diferentes, basta somar os extremos: a maior com a menor.

Se houver apenas duas margens, some elas.

Se houver mais de duas, ignore as margens com valores intermediários no cálculo.

Margin collapsing com margens de sinais diferentes
Margins envolvidas no collapsingCálculoMargin final
35px35px + (-15px)20px
5px
-10px
-15px

E agora finalmente, como se livrar desse incômodo.

Como corrigir o margin collapsing?

Você se lembra do capítulo Quando o margin collapsing acontece? Agora você verá como corrigi-lo, ou Quando o margin collapsing não acontece.

Para isso, basta apenas quebrar uma das exigências do margin collapsing. Existem muitas formas de fazer isso. Veja algumas:

Use float

Obs: não use mais float :) flexbox e grid estão aí para isso.

Mas se usar, saiba que não haverá margin collapsing em elementos flutuantes.

Resolve os seguintes casos:

  • Elementos irmãos próximos

  • Elemento pai com primeiro e último filho

  • Elemento vazio

Use position

Um elemento posicionado não irá causar margin collapsing.

Isso vale tanto para position: absolute, quanto para position: fixed.

Resolve os seguintes casos:

  • Elementos irmãos próximos

  • Elemento pai com primeiro e último filho

  • Elemento vazio

Use padding

No começo do post, eu disse que o collapsing acontece quando duas margens se encostam. Logo, se as margens não se encostam, não acontece o collapsing.

A forma mais simples de fazer isso é adicionar um padding em um dos elementos.

Resolve os seguintes casos:

  • Elemento pai com primeiro e último filho

  • Elemento vazio

Use border

A borda é outro componente do box model que, ao ser inserida, impede o margin collapsing.

Resolve os seguintes casos:

  • Elemento pai com primeiro e último filho

  • Elemento vazio

Use propriedades de altura

Essas propriedades de altura evitam o margin collapsing:

  • height

  • min-height

  • max-height

  • line-height

A regra diz que as margens precisam se tocar para acontecer o collapsing. Logo, definir uma altura é o suficiente para separá-las.

Resolve os seguintes casos:

  • Elemento pai com primeiro e último filho

  • Elemento vazio

Use overflow

Se o elemento pai tiver uma barra de rolagem em função da propriedade overflow, não haverá margin collapsing. Isso acontece tanto com overflow: scroll, quanto com overflow: auto.

É importante que esse elemento também não seja vazio.

Resolve os seguintes casos:

  • Elemento pai com primeiro e último filho

Insira um conteúdo entre as bordas

O margin collapsing não acontece caso haja qualquer conteúdo entre as duas (ou mais) margens.

Esse conteúdo pode ser até a tag <br />. Mas venhamos e convenhamos, você não vai fazer isso né?

Resolve os seguintes casos:

  • Elemento pai com primeiro e último filho

  • Elemento vazio

Use flexbox ou grid

A maravilha do CSS moderno.

Se você colocar display: flex / grid em um elemento, não irá acontecer o margin collapsing entre seus filhos.

Resolve os seguintes casos:

  • Elementos irmãos próximos

Some a isso, o fato de você poder separar elementos dentro de flexbox e grid com a propriedade gap do CSS . A maioria dos navegadores modernos já suporta essa propriedade, segundo o Can I Use . Assim, nem é preciso usar margin.

Callback

Margin collapsing é quando o margin-top/margin-bottom de um elemento se junta com o de outro ou do mesmo elemento.

Acontece entre:

  • Elementos irmãos próximos

  • Elemento pai com primeiro e último filho

  • E elementos vazios

Pode acontecer com mais de duas margens ao mesmo tempo.

Dependendo do valor das margens envolvidas, o valor final pode variar bastante em função do cálculo.

Existem também diversas formas de corrigir o margin collapsing, e cada uma se aplica a uma situação diferente.

O que achou? Diferente de mim, você encontra muito margin collapsing no seu dia a dia?

Comente aqui aqui embaixo!

Muito obrigado pela sua leitura 🙂


Continue estudando:

Veja outros posts sobre Front-end