Como funcionam as margens negativas em CSS e por que (margin-top: -5! = Margin-bottom: 5)?


108

Um truque comum para elementos de posicionamento vertical é usar o seguinte CSS:

.item {
    position:absolute;
    top:50%;
    margin-top:-8px; /* half of height */
    height: 16px;
}

Quando visto na visualização métrica como no Chrome, isto é o que você vê:

insira a descrição da imagem aqui

No entanto, não há margem visual representada quando você passa o mouse sobre o elemento, ou seja, a margem está 'fora' da borda e pode ser visualizada. Mas as margens negativas não aparecem. Como eles se parecem e o que os torna diferentes?

Por que margin-top:-8px não é o mesmo quemargin-bottom:8px ?

Então, como as margens negativas funcionam e qual é a intuição por trás delas. Como eles 'aumentam' (no caso de margin-top < 0) um item?

Respostas:


89

As margens negativas são válidas em css e a compreensão de seu comportamento (compatível) se baseia principalmente no modelo de caixa e no colapso da margem. Embora certos cenários sejam mais complexos, muitos erros comuns podem ser evitados após estudar as especificações.

Por exemplo, a renderização do seu código de amostra é guiada pela especificação css conforme descrito no cálculo de alturas e margens para elementos não substituídos absolutamente posicionados .

Se eu fosse fazer uma representação gráfica, provavelmente optaria por algo assim (não em escala):

margem superior negativa

A caixa de margem perdida 8pxno topo, no entanto, isso não afeta as caixas de conteúdo e preenchimento . Como seu elemento está absolutamente posicionado, movê-lo 8px para cima não causa mais perturbações no layout; com conteúdo estático em fluxo, esse nem sempre é o caso.

Bônus:

Ainda precisa ser convencido de que ler as especificações é o caminho a percorrer (ao contrário de artigos como este )? Vejo que você está tentando centralizar verticalmente o elemento, então por que você tem que definir margin-top:-8px;e não margin-top:-50%;?

Bem, a centralização vertical em CSS é mais difícil do que deveria . Ao definir as margens superior ou inferior em%, o valor é calculado como uma porcentagem sempre em relação à largura do bloco que o contém . Esta é uma armadilha comum e raramente é descrita fora do w3 docos


84

Vou tentar explicar visualmente:

/**
 * explaining margins
 */

body {
  padding: 3em 15%
}

.parent {
  width: 50%;
  width: 400px;
  height: 400px;
  position: relative;
  background: lemonchiffon;
}

.parent:before,
.parent:after {
  position: absolute;
  content: "";
}

.parent:before {
  top: 0;
  bottom: 0;
  left: 50%;
  border-left: dashed 1px #ccc;
}

.parent:after {
  left: 0;
  right: 0;
  top: 50%;
  border-top: dashed 1px #ccc;
}

.child {
  width: 200px;
  height: 200px;
  background: rgba(200, 198, 133, .5);
}

ul {
  padding: 5% 20px;
}

.set1 .child {
  margin: 0;
  position: relative;
}

.set2 .child {
  margin-left: 75px;
  position: relative;
}

.set3 .child {
  margin-left: -75px;
  position: relative;
}


/* position absolute */

.set4 .child {
  top: 50%;
  left: 50%;
  margin: 0;
  position: absolute;
}

.set5 .child {
  top: 50%;
  left: 50%;
  margin-left: 75px;
  position: absolute;
}

.set6 .child {
  top: 50%; /* level from which margin-top starts 
	- downwards, in the case of a positive margin
	- upwards, in the case of a negative margin	
	*/
  left: 50%; /* level from which margin-left starts 
	- towards right, in the case of a positive margin
	- towards left, in the case of a negative margin	
	*/
  margin: -75px;
  position: absolute;
}
<!-- content to be placed inside <body>…</body> -->
<h2><code>position: relative;</code></h2>
<h3>Set 1</h3>
<div class="parent set 1">
  <div class="child">
    <pre>
.set1 .child {
  margin: 0;
  position: relative;
}
		</pre>
  </div>
</div>

<h3>Set 2</h3>
<div class="parent set2">
  <div class="child">
    <pre>
.set2 .child {
  margin-left: 75px;
  position: relative;
}
		</pre>
  </div>
</div>

<h3>Set 3</h3>
<div class="parent set3">
  <div class="child">
    <pre>
.set3 .child {
  margin-left: -75px;
  position: relative;
}
		</pre>
  </div>
</div>

<h2><code>position: absolute;</code></h2>

<h3>Set 4</h3>
<div class="parent set4">
  <div class="child">
    <pre>
.set4 .child {
  top: 50%;
  left: 50%;
  margin: 0;
  position: absolute;
}
		</pre>
  </div>
</div>

<h3>Set 5</h3>
<div class="parent set5">
  <div class="child">
    <pre>
.set5 .child {
  top: 50%;
  left: 50%;
  margin-left: 75px;
  position: absolute;
}
		</pre>
  </div>
</div>

<h3>Set 6</h3>
<div class="parent set6">
  <div class="child">
    <pre>
.set6 .child {
  top: 50%;
  left: 50%;
  margin: -75px;
  position: absolute;
}
		</pre>
  </div>
</div>


33

Margem é o espaçamento fora do seu elemento, assim como o preenchimento é o espaçamento dentro do seu elemento.

Definir a margem inferior indica a distância que você deseja abaixo do bloco atual. Definir uma margem superior negativa indica que você deseja espaçamento negativo acima do bloco. O espaçamento negativo pode ser um conceito confuso, mas da mesma forma que a margem superior positiva empurra o conteúdo para baixo, uma margem superior negativa empurra o conteúdo para cima.


2
1 Eu gosto da sua resposta. Pode ser melhorado injetando-se as palavras onsete offset. É verdade que muitas pessoas sempre usam a palavra offset( negativo ) quando querem dizer onset( positivo ). Esta mensagem se autodestruirá se você atualizar sua resposta. Felicidades!
arttronics

1
Sobre o quê margin-bottom: -8px;? Por que margin-bottom:-8pxnão é o mesmo que margin-top:-8px?
Rick

27

Uma margem superior de -8px significa que será 8px maior do que se tivesse 0 de margem.

Uma margem inferior de 8px significa que a coisa abaixo dela estará 8px mais abaixo do que se tivesse 0 de margem.


1
Eu estava apenas tentando manter as coisas simples, mas concordo, esta é possivelmente a pior das minhas respostas!
Rich Bradshaw

2
Eu acho que a resposta é muito boa. Não adianta respostas altamente técnicas que metade de nós não entende.
945 de

1
Sobre o quê margin-bottom: -8px;? Por que margin-bottom:-8pxnão é o mesmo que margin-top:-8px?
Rick

22

bons pontos já feitos aqui, mas embora haja muitas informações sobre como a renderização de margens é realizada pelo navegador, o porquê ainda não foi respondido:

"Por que margin-top: -8px não é o mesmo que margin-bottom: 8px?"

o que também podemos perguntar é:

Por que uma margem inferior positiva não 'empurra' os elementos anteriores, enquanto uma margem superior positiva 'desce' os elementos seguintes?

então o que vemos é que há uma diferença na renderização das margens dependendo do lado em que são aplicadas - as margens superior (e esquerda) são diferentes das inferiores (e direita).

as coisas estão se tornando mais claras quando temos uma visão (simplificada) de como os estilos são aplicados pelo navegador: os elementos são renderizados de cima para baixo na janela de visualização, começando no canto superior esquerdo (vamos ficar com a renderização vertical por enquanto, tendo em mente que o horizontal é tratado da mesma forma).

considere o seguinte html:

<div class="box1"></div>
<div class="box2"></div>
<div class="box3"></div>

analogamente à sua posição no código, essas três caixas aparecem empilhadas 'de cima para baixo' no navegador ( mantendo as coisas simples, não consideraremos aqui a orderpropriedade do módulo css3 'flex-box' ). portanto, sempre que os estilos são aplicados à caixa 3, as posições dos elementos precedentes (para as caixas 1 e 2) já foram determinadas e não devem mais ser alteradas por causa da velocidade de renderização.

agora, imagine uma margem superior de -10px para a caixa 3. em vez de deslocar todos os elementos anteriores para reunir algum espaço, o navegador apenas empurrará a caixa 3 para cima, então ela é renderizada em cima (ou embaixo, dependendo do Z-index ) quaisquer elementos anteriores. mesmo que o desempenho não fosse um problema, mover todos os elementos para cima poderia significar deslocá-los para fora da janela de visualização, portanto, a posição de rolagem atual teria que ser alterada para ter tudo visível novamente.

o mesmo se aplica a uma margem inferior para a caixa 3, tanto negativa quanto positiva: em vez de influenciar os elementos já avaliados, apenas um novo 'ponto de partida' para os próximos elementos é determinado. assim, definir uma margem inferior positiva empurrará os seguintes elementos para baixo; um negativo irá empurrá-los para cima.


A MELHOR resposta. Esta também explica o "porquê", enquanto as outras respostas apenas explicam o "como".
Amir Hossein Ahmadi

1
Essa resposta me ajudou a entender melhor o porquê. Obrigado @schellmax
iRamesh

3

Como você usou o posicionamento absoluto e especificou uma porcentagem superior, apenas a margem superior afetará a localização do seu objeto .item. Se, em vez disso, você o posicionou usando bottom: 50%, então você precisaria do margin-bottom -8px para centralizá-lo, e o margin-top não teria efeito.

A margem afeta os limites de um elemento em termos de posicionamento, seja absolutamente como no seu caso, ou em relação aos elementos vizinhos. Imagine que a margem é a base do seu elemento no qual ela se assenta. Eles são normalmente do mesmo tamanho, mas podem ser maiores ou menores em qualquer uma ou em todas as quatro bordas.

Seu CSS diz ao navegador para posicionar a parte superior do seu elemento na margem em um ponto 50% do caminho para baixo na página. No entanto, como todos os elementos não são um único pixel, o navegador precisa saber qual parte dele deve se alinhar 50% da página. Para alinhar a parte superior do elemento, ele usa a margem superior. Por padrão, ele está alinhado com a parte superior do elemento, mas você pode alterá-lo com CSS.

No seu caso, os 50% superiores resultariam na parte superior do elemento começando no meio da página. Ao aplicar uma margem superior negativa, o navegador usa o ponto 8px no elemento a partir do topo (ou seja, a linha no meio dele) como o lugar para posicionar em 50%.

Se você aplicar uma margem positiva na parte inferior, isso estende a linha que o navegador usa para posicionar a parte inferior longe do próprio elemento, deixando uma lacuna entre ele e qualquer elemento adjacente abaixo, ou afetando onde ele é colocado absolutamente se o posicionamento for baseado em o fundo.


+1. Faz sentido ... seria ótimo aumentá-lo com dicas visuais para completar a visualização .
PhD de

3

Gostaria de saber se esta questão foi respondida bem: como funcionam as margens css e porque é que margin-top: -5; não é o mesmo que margin-bottom: 5 ;?

A margem é a distância dos arredores do elemento. margin-top diz "... distância dos arredores conforme medimos do topo 'lado' da 'caixa' do elemento e margin-bottom sendo a distância do fundo 'lado' da 'caixa'". Em seguida, margem superior: 5; refere-se ao perímetro "lateral" superior, -5 nesse caso; qualquer coisa que se aproxime do 'lado' superior pode se sobrepor ao 'lado' superior do elemento em 5, e a margem inferior: 5; significa que a distância entre o 'lado' inferior do elemento e o entorno é 5.

Basicamente isso, mas afetado por elementos flutuantes e similares: http://www.w3.org/TR/CSS2/box.html#margin-properties .

http://coding.smashingmagazine.com/2009/07/27/the-definitive-guide-to-using-negative-margins/

Eu espero ser corrigido.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.