Tudo o que você precisa saber sobre margens CSS

Publicados: 2022-03-10
Resumo rápido ↬ As margens em CSS parecem bastante simples à primeira vista. Aplicado a um elemento, ele forma um espaço ao redor do elemento, afastando outros elementos. No entanto, há mais margem do que você imagina.

Uma das primeiras coisas que a maioria de nós aprendeu quando aprendemos CSS, foram os detalhes das várias partes de uma caixa em CSS, descrita como The CSS Box Model. Um dos elementos do Box Model é a margem, uma área transparente ao redor de uma caixa, que afastará outros elementos do conteúdo da caixa. As propriedades margin-top , margin-right , margin-bottom e margin-left foram descritas no CSS1, juntamente com a margin abreviada para definir todas as quatro propriedades de uma vez.

Uma margem parece ser uma coisa bastante simples, no entanto, neste artigo, vamos dar uma olhada em algumas das coisas que enganam as pessoas em relação ao uso de margens. Em particular, veremos como as margens interagem umas com as outras e como o colapso das margens realmente funciona.

O modelo de caixa CSS

Como em todos os artigos sobre partes do CSS Box Model, devemos definir o que queremos dizer com isso e como o modelo foi esclarecido por meio de versões do CSS. O modelo de caixa refere-se a como as várias partes de uma caixa - o conteúdo, preenchimento, borda e margem - são dispostas e interagem umas com as outras. No CSS1, o Box Model foi detalhado com o diagrama de arte ASCII mostrado na imagem abaixo.

desenho de arte ascii do modelo de caixa
Representação do modelo de caixa CSS em CSS1

As quatro propriedades de margem para cada lado da caixa e a abreviação de margin foram todas definidas em CSS1.

A especificação CSS2.1 tem uma ilustração para demonstrar o Box Model e também define termos que ainda usamos para descrever as várias caixas. A especificação descreve a content box de padding box de border box e margin box , cada uma sendo definida pelas bordas do conteúdo, preenchimento, borda e margem, respectivamente.

diagrama do modelo de caixa CSS
Depection do CSS Box Model em CSS2

Existe agora uma especificação de modelo de caixa de nível 3 como um rascunho de trabalho. Esta especificação se refere ao CSS2 para as definições do Box Model e margens, portanto, é a definição CSS2 que usaremos na maior parte deste artigo.

Mais depois do salto! Continue lendo abaixo ↓

Recolhimento de margem

A especificação CSS1, como definiu as margens, também definiu que as margens verticais são colapsadas . Esse comportamento de colapso tem sido a fonte de frustração relacionada à margem desde então. O recolhimento de margem faz sentido se você considerar que naqueles primeiros dias, o CSS estava sendo usado como uma linguagem de formatação de documentação. O recolhimento de margem significa que quando um título com uma margem inferior é seguido por um parágrafo com uma margem superior, você não obtém uma grande lacuna entre esses itens.

Quando as margens colapsam, elas se combinam para que o espaço entre os dois elementos se torne o maior das duas margens. A margem menor termina essencialmente dentro da maior.

As margens caem nas seguintes situações:

  • irmãos adjacentes
  • Caixas completamente vazias
  • Pai e primeiro ou último elemento filho

Vamos dar uma olhada em cada um desses cenários, antes de olhar para as coisas que impedem o colapso das margens nesses cenários.

Irmãos Adjacentes

Minha descrição inicial do colapso das margens é uma demonstração de como as margens entre irmãos adjacentes colapsam. Exceto nas situações mencionadas abaixo, se você tiver dois elementos exibindo um após o outro em fluxo normal, a margem inferior do primeiro elemento será colapsada com a margem superior do elemento seguinte.

No exemplo do CodePen abaixo, existem três elementos div . O primeiro tem uma margem superior e inferior de 50 pixels. O segundo tem uma margem superior e inferior de 20px. O terceiro tem uma margem superior e inferior de 3em. A margem entre os dois primeiros elementos é de 50 pixels, pois a margem superior menor é combinada com a margem inferior maior. A margem entre os dois segundos elementos em 3em, pois 3em é maior que os 20 pixels na parte inferior do segundo elemento.

Veja a Caneta [Margens: irmãos adjacentes](https://codepen.io/rachelandrew/pen/OevMPo) por Rachel Andrew.

Veja as margens da caneta: irmãos adjacentes por Rachel Andrew.

Caixas completamente vazias

Se uma caixa estiver vazia, suas margens superior e inferior podem colapsar uma com a outra. No exemplo do CodePen a seguir, o elemento com uma classe vazia tem uma margem superior e inferior de 50 pixels, no entanto, o espaço entre o primeiro e o terceiro item não é de 100 pixels, mas de 50. Isso ocorre devido à redução das duas margens. Adicionar qualquer coisa a essa caixa (mesmo preenchimento) fará com que as margens superior e inferior sejam usadas e não sejam recolhidas.

Veja a Caneta [Margens: caixas vazias](https://codepen.io/rachelandrew/pen/JQLGMr) de Rachel Andrew.

Veja as margens da caneta: caixas vazias por Rachel Andrew.

Pai e primeiro ou último elemento filho

Este é o cenário de colapso de margem que surpreende as pessoas com mais frequência, pois não parece particularmente intuitivo. No CodePen a seguir, tenho uma div com uma classe de wrapper e dei a essa div um outline em vermelho para que você possa ver onde está. Os três elementos filho têm uma margem de 50 pixels. No entanto, o primeiro e o último itens estão alinhados com as bordas do invólucro; não há uma margem de 50 pixels entre o elemento e o wrapper.

Veja a Caneta [Margens: margem no primeiro e último filho](https://codepen.io/rachelandrew/pen/BgrKGp) de Rachel Andrew.

Veja as margens da caneta: margem no primeiro e último filho por Rachel Andrew.

Isso ocorre porque a margem do filho colapsa com qualquer margem do pai, terminando do lado de fora do pai. Você pode ver isso se inspecionar o primeiro filho usando o DevTools. A área amarela destacada é a margem.

O item com uma margem destacada em amarelo mostrando fora do pai
DepvTools pode ajudá-lo a ver onde sua margem termina

Apenas Bloquear Margens Recolher

O último exemplo também destaca algo sobre o colapso da margem. No CSS2, apenas as margens verticais são especificadas para serem recolhidas — ou seja, as margens superior e inferior de um elemento se você estiver no modo de escrita horizontal. Portanto, as margens esquerda e direita acima não estão colapsando e terminando fora do wrapper.

Nota : Vale lembrar que as margens só colapsam na direção do bloco, como entre parágrafos.

Coisas que impedem o colapso da margem

As margens nunca são recolhidas se um item tiver posicionamento absoluto ou flutuar. No entanto, supondo que você tenha se deparado com um dos lugares onde as margens se contraem descritos acima, como você pode impedir que essas margens entrem em colapso?

A primeira coisa que para de desmoronar são as situações em que há algo entre os elementos em questão.

Por exemplo, uma caixa completamente vazia de conteúdo não recolherá suas margens superior e inferior se tiver uma borda ou preenchimento aplicado. No exemplo abaixo, adicionei 1px de preenchimento à caixa. Agora há uma margem de 50 pixels acima e abaixo da caixa.

Veja a Caneta [Margens: caixas vazias com preenchimento não colapsam](https://codepen.io/rachelandrew/pen/gNeMpg) de Rachel Andrew.

Veja as margens da caneta: caixas vazias com preenchimento não colapsam por Rachel Andrew.

Isso tem lógica por trás disso, se a caixa estiver completamente vazia, sem borda ou preenchimento, é essencialmente invisível. Pode ser um elemento de parágrafo vazio lançado na marcação pelo seu CMS. Se o seu CMS estivesse adicionando elementos de parágrafo redundantes, você provavelmente não gostaria que eles causassem grandes lacunas entre os outros parágrafos devido ao fato de suas margens serem respeitadas. Adicione qualquer coisa à caixa e você obterá essas lacunas.

Comportamento semelhante pode ser visto com margens no primeiro ou último filho que colapsam através do pai. Se adicionarmos uma borda ao pai, as margens dos filhos ficarão dentro.

Veja a Caneta [Margens: margem no primeiro e último filho não colapsa se o pai tiver uma borda](https://codepen.io/rachelandrew/pen/vqRKKX) por Rachel Andrew.

Veja as margens da caneta: a margem no primeiro e no último filho não colapsa se o pai tiver uma borda de Rachel Andrew.

Mais uma vez, há alguma lógica no comportamento. Se você tiver elementos de encapsulamento para fins semânticos que não são exibidos visualmente, provavelmente não deseja que eles introduzam grandes lacunas na exibição. Isso fazia muito sentido quando a web era principalmente texto. É menos útil como comportamento quando estamos usando elementos para criar um design.

Criando um contexto de formatação de bloco

Um novo Contexto de Formatação de Bloco (BFC) também impedirá o recolhimento da margem através do elemento que o contém. Se olharmos novamente para o exemplo do primeiro e do último filho, terminando com suas margens fora do wrapper, e dermos ao wrapper display: flow-root , criando assim um novo BFC, as margens ficam dentro.

Veja a Caneta [Margens: um novo contexto de formatação de bloco contém margens](https://codepen.io/rachelandrew/pen/VJXjEp) por Rachel Andrew.

Veja as margens da caneta: um novo contexto de formatação de bloco contém margens de Rachel Andrew.

Para saber mais sobre display: flow-root , leia meu artigo “Entendendo o layout CSS e o contexto de formatação de bloco”. Alterar o valor da propriedade overflow para auto terá o mesmo efeito, pois isso também cria um novo BFC, embora também possa criar barras de rolagem que você não queria em alguns cenários.

Contêineres Flex e Grade

Os contêineres Flex e Grid estabelecem contextos de formatação Flex e Grid para seus filhos, então eles têm um comportamento diferente para bloquear o layout. Uma dessas diferenças é que as margens não colapsam:

“Um contêiner flexível estabelece um novo contexto de formatação flexível para seu conteúdo. Isso é o mesmo que estabelecer um contexto de formatação de bloco, exceto que o layout flexível é usado em vez do layout de bloco. Por exemplo, floats não invadem o container flex, e as margens do container flex não colapsam com as margens de seu conteúdo.”

— Flexbox Nível 1

Se pegarmos o exemplo acima e transformarmos o wrapper em um contêiner flex, exibindo os itens com flex-direction: column , você verá que as margens agora estão contidas no wrapper. Além disso, as margens entre os itens flexíveis adjacentes não colapsam entre si, então acabamos com 100 pixels entre os itens flexíveis, o total dos 50 pixels na parte superior e inferior dos itens.

Veja a Caneta [Margens: as margens em itens flexíveis não são recolhidas](https://codepen.io/rachelandrew/pen/mZxreL) por Rachel Andrew.

Veja as margens da caneta: as margens em itens flexíveis não são recolhidas por Rachel Andrew.

Estratégias de margem para seu site

Devido ao colapso das margens, é uma boa ideia criar uma maneira consistente de lidar com as margens do seu site. A coisa mais simples a fazer é definir apenas as margens na parte superior ou inferior dos elementos. Dessa forma, você não deve se deparar com problemas de colapso de margem com muita frequência, pois o lado com margem sempre estará adjacente a um lado sem margem.

Nota : Harry Roberts tem um excelente post detalhando as razões pelas quais definir margens apenas em uma direção é uma boa ideia, e não apenas devido à solução de problemas de margens em colapso.

Essa solução não resolve os problemas que você pode encontrar com margens em filhos que colapsam por meio de seus pais. Esse problema específico tende a ser menos comum, e saber por que isso está acontecendo pode ajudá-lo a encontrar uma solução. Uma solução ideal para isso é fornecer componentes que exigem display: flow-root , como um substituto para navegadores mais antigos, você pode usar overflow para criar um BFC, transformar o pai em um contêiner flexível ou até mesmo introduzir um único pixel de preenchimento. Não se esqueça de que você pode usar consultas de recursos para detectar suporte para display: flow-root para que apenas navegadores antigos obtenham uma correção menos otimizada.

Na maioria das vezes, acho que saber por que as margens colapsam (ou não) é a chave. Você pode então descobrir caso a caso como lidar com isso. Seja qual for a sua escolha, certifique-se de compartilhar essas informações com sua equipe. Muitas vezes, o colapso de margem é um pouco misterioso, então a razão para fazer as coisas para combatê-lo pode não ser óbvia! Um comentário em seu código ajuda bastante — você pode até criar um link para este artigo e ajudar a compartilhar o conhecimento sobre o colapso da margem.

Eu pensei em reunir este artigo com algumas outras informações relacionadas à margem.

Margens percentuais

Quando você usa uma porcentagem em CSS, tem que ser uma porcentagem de alguma coisa. As margens (e preenchimento) definidas usando porcentagens sempre serão uma porcentagem do tamanho embutido (largura em um modo de escrita horizontal) do pai. Isso significa que você terá preenchimento de tamanho igual em todo o elemento ao usar porcentagens.

No exemplo do CodePen abaixo, tenho um wrapper com 200 pixels de largura, dentro está uma caixa que tem uma margem de 10%, a margem é de 20 pixels em todos os lados, sendo 10% de 200.

Veja a Caneta [Margens: margens percentuais](https://codepen.io/rachelandrew/pen/orqzrP) de Rachel Andrew.

Veja as margens da caneta: margens percentuais por Rachel Andrew.

Margens em um mundo relativo ao fluxo

Temos falado sobre margens verticais ao longo deste artigo, no entanto, o CSS moderno tende a pensar sobre as coisas em um fluxo relativo em vez de uma maneira física. Portanto, quando falamos de margens verticais, estamos realmente falando de margens na dimensão do bloco. Essas margens serão superior e inferior se estivermos em um modo de escrita horizontal, mas serão direita e esquerda em um modo de escrita vertical escrito da esquerda para a direita.

Uma vez trabalhando com direções relativas de fluxo lógicas, torna-se mais fácil falar sobre o início e o fim do bloco, em vez de superior e inferior. Para tornar isso mais fácil, o CSS introduziu a especificação Logical Properties and Values. Isso mapeia as propriedades relativas do fluxo para as físicas.

Para margens, isso nos fornece os seguintes mapeamentos (se estivermos trabalhando em inglês ou qualquer outro modo de escrita horizontal com direção de texto da esquerda para a direita).

  • margin-top = margin-block-start
  • margin-right = margin-inline-end
  • margin-bottom = margin-block-end
  • margin-left = margin-inline-start

Também temos dois novos atalhos que permitem a configuração de ambos os blocos de uma só vez ou ambos inline.

  • margin-block
  • margin-inline

No próximo exemplo do CodePen, usei essas palavras-chave relativas ao fluxo e, em seguida, alterei o modo de escrita da caixa, você pode ver como as margens seguem a direção do texto, em vez de serem vinculadas ao topo, à direita, ao fundo e à esquerda físicos.

Veja a Caneta [Margens: margens relativas do fluxo](https://codepen.io/rachelandrew/pen/BgrQRj) de Rachel Andrew.

Veja as margens da caneta: margens relativas de fluxo por Rachel Andrew.

Você pode ler mais sobre propriedades e valores lógicos no MDN ou no meu artigo “Entendendo propriedades e valores lógicos” aqui na Smashing Magazine.

Para encerrar

Agora você sabe mais do que há para saber sobre margens! Resumidamente:

  • O colapso da margem é uma coisa. Compreender por que isso acontece e quando isso não acontece irá ajudá-lo a resolver quaisquer problemas que possa causar.
  • Definir margens em uma direção só resolve muitas dores de cabeça relacionadas à margem.
  • Como com qualquer coisa em CSS, compartilhe com sua equipe as decisões que você toma e comente seu código.
  • Pensar nas dimensões de bloco e em linha, em vez das dimensões físicas superior, direita, inferior e esquerda, ajudará você à medida que a web se move para ser agnóstica do modo de escrita.