Margin-Top push div externa para baixo

126

Eu tenho uma div de cabeçalho como o primeiro elemento em minha div de wrapper, mas quando adiciono uma margem superior a uma h1 dentro da div de cabeçalho, ela empurra toda a div de cabeçalho para baixo. Percebo que isso acontece sempre que aplico uma margem superior ao primeiro elemento visível em uma página.

Aqui está um trecho de código de exemplo. Obrigado!

div#header{
	width: 100%;
	background-color: #eee;
	position: relative;
}

div#header h1{
	text-align: center;
	width: 375px;
	height: 50px;
	margin: 50px auto;
	font-size: 220%;
	background: url('../../images/name_logo.png') no-repeat;
}
<div id="header">
	<h1>Title</h1>
	<ul id="navbar"></ul>
</div>

Danny
fonte

Respostas:

193

colocar overflow:autono pai div
veja mais neste link

Juan Pablo
fonte
29
overflow:hiddené melhor para 90% dos casos.
vsync
1
Por que overflow: hidden seria melhor?
Peterchon 25/10
5
@peterchon - porque auto pode causar barras de rolagem
vsync
3
não funciona mais, a resposta por @ SW4 nesta ligação é melhor
am05mhz
1
overflow: hiddenou overflow: autopode causar efeitos colaterais indesejados, alguns dos quais você pode não ver à primeira vista. Eu descobri que mudar marginpara paddingfaz o truque, como a resposta abaixo sugere. Ainda não entendo por que todo o problema acontece.
Gilad Barner
34

Não tenho uma explicação sólida sobre o motivo disso acontecer, mas corrigi isso alterando o top-marginpara top-paddingou adicionando display: inline-blockao estilo do elemento.

EDIT: Esta é a minha teoria

Sinto que isso tem algo a ver com a forma como as margens são recolhidas (combinadas).

das margens colapsadas do W3C :

Nesta especificação, a expressão margens recolhidas significa que margens adjacentes (sem conteúdo não vazio, áreas de preenchimento ou borda ou folga as separam) de duas ou mais caixas (que podem estar próximas umas das outras ou aninhadas) se combinam para formar uma única margem .

Minha teoria é que, como seu primeiro elemento é próximo ao corpo, as duas margens se combinam e são aplicadas ao corpo: isso força o conteúdo do corpo a começar abaixo da margem recolhida aplicada, em conformidade com o modelo de caixa .

Há situações em que as margens não são reduzidas e que podem valer a pena brincar (nas margens de recolhimento ):

* floated elements
* absolutely positioned elements
* inline-block elements
* elements with overflow set to anything other than visible (They do not collapse margins with their children.)
* cleared elements (They do not collapse their top margins with their parent block’s bottom margin.)
* the root element
digitaldreamer
fonte
3
Além disso, o preenchimento ou a borda do elemento com margem recolhida (a interna) irá retirá-lo.
Anonymous
Isso funcionou para mim - eu tinha elementos absolutos (um menu suspenso) no meu contêiner, então estouro: auto não funcionou.
Mwilcox 22/05
17

Essas são algumas das maneiras de evitar o colapso da margem entre os elementos pai-filho. Use o que se encaixa melhor com o resto do seu estilo:

  • Defina displaycomo diferente de block.
  • Defina floatcomo diferente de none.
  • Remova a margem e use padding. Por exemplo, se você tiver margin-top: 10px, substitua por padding-top: 10px;.
  • Retirar a margem e usar em vez position( absoluteou relative) com atributos top, bottometc. Por exemplo, se você tivesse margin-top: 10px, substitua com position: relative; top: 10px;.
  • Adicione um paddingou a borderno lado em que as margens estão recolhendo, ao elemento pai . A borda pode ser 1px e transparente.
  • Definir overflowpara que não seja visiblepara o pai elemento.
Jesús Carrera
fonte
5

Sei que esse é um problema antigo, já o encontrei muitas vezes. O problema é que todas as correções aqui são hacks que potencialmente teriam conseqüências não intencionais.

Primeiro, há uma explicação fácil para o problema raiz. Devido ao modo como o colapso da margem funciona, se o primeiro elemento dentro de um contêiner tiver uma margem superior, essa margem superior será efetivamente aplicada ao próprio contêiner pai. Você pode testar isso sozinho, fazendo o seguinte:

<div>
    <h1>Test</h1>
</div>

Em um depurador, abra isso e passe o mouse pela div. Você notará que o div em si é realmente colocado onde a margem superior do elemento H1 para . Esse comportamento é pretendido pelo navegador.

Portanto, existe uma solução fácil para isso sem ter que recorrer a hacks estranhos, como a maioria das postagens aqui faz (sem insultos, é apenas a verdade) - basta voltar à explicação original - ...if the first element inside a container has a top margin...- Depois disso, você precisará o primeiro elemento em um contêiner a NÃO ter uma margem superior. Ok, mas como você faz isso sem adicionar elementos que não interferem semanticamente no seu documento?

Fácil! Pseudo-elementos! Você pode fazer isso por meio de uma classe ou um mixin predefinido. Adicione um :beforepseudoelemento:

CSS por meio de uma classe:

.top-margin-fix:before {   
    content: ' ';
    display: block;
    width: 100%;
    height: .0000001em;
}

Com isso, seguindo o exemplo de marcação acima, você modificaria sua div assim:

<div class="top-margin-fix">
    <h1>Test</h1>
</div>

Por que isso funciona?

O primeiro elemento em um contêiner, se não tiver margem superior, define a posição do início da margem superior do próximo elemento. Ao adicionar um :beforepseudoelemento, o navegador realmente adiciona um elemento não-semântico (em outras palavras, bom para SEO) ao contêiner pai antes do seu primeiro elemento.

Q. Por que a altura: .0000001em?

R. É necessária uma altura para o navegador empurrar o elemento de margem para baixo. Essa altura é efetivamente zero, mas ainda permitirá adicionar preenchimento ao próprio contêiner pai. Como é efetivamente zero, também não afetará o layout do contêiner. Lindo.

Agora você pode adicionar uma classe (ou melhor, em SASS / LESS, um mixin!) Para corrigir esse problema, em vez de adicionar estilos de exibição estranhos que causarão consequências inesperadas quando você quiser fazer outras coisas com seus elementos, eliminando propositadamente as margens dos elementos. e / ou substituí-lo por preenchimento ou estilos estranhos de posição / flutuação que realmente não pretendem resolver esse problema.

dudewad
fonte
2
O .0000001em é realmente arredondado para zero no IE11, interrompendo sua correção. Quando eu mudo para .01em, ele funciona.
Esger
1
Imagino que .01em seja suficiente para ainda ser efetivamente zero. Bom ponto. Por outro lado, agora que é 2018, muitos de nós abandonaremos o suporte para o IE11 em breve, especialmente com o recente anúncio de que a MS estará novamente construindo um novo navegador (exceto desta vez, com base no cromo, o que significa que - teoricamente - não vai chupar totalmente). : D
dudewad
2

display: flexfuncionará neste caso. Forneça o elemento pai display: flex;e, em seguida, dê margem conforme sua exigência para a h1tag.

Bijay
fonte
0

Encontre este problema hoje.

overflow: hidden não funcionou como esperado quando eu tinha mais elementos seguidos.

Então, eu tentei alterar a propriedade de exibição da div pai e display: flexfuncionou !!!

Espero que isso ajude alguém. :)

Libin
fonte
0

Adicionar um pouco de preenchimento à parte superior do elemento pai pode corrigir esse problema.

.parent{
  padding-top: 0.01em;
}

Isso é útil se você precisar que um elemento dentro do pai esteja visível fora do elemento pai, como se estivesse criando um efeito sobreposto.

adamspruijt
fonte
0

Isso acontece devido ao colapso da margem. Quando o elemento filho tocar no limite do elemento pai e qualquer um deles aplicado com margens, então:

  1. A margem que for maior ganhará (aplicada).

  2. se algum deles tiver margem, ambos compartilharão o mesmo.

Soluções

  1. aplicar borda ao pai, o que separa pai e filho.
  2. aplique preenchimento ao pai, o que separa pai e filho.
  3. aplique excesso em vez de visível no pai.
  4. use before ou after para criar elemento virtual na div pai, que pode diferir filho e pai aplicados à margem.
  5. criar um elemento html entre filho aplicado de margem e pai também pode separá-los.
Ishu
fonte