web-dev-qa-db-fra.com

Pourquoi ce style CSS margin-top ne fonctionne-t-il pas?

J'essaie d'ajouter des valeurs de marge sur une div à l'intérieur d'une autre div. Tout fonctionne bien, sauf la valeur maximale, il semble être ignoré. Mais pourquoi?

Ce à quoi je m'attendais:
What I expected with margin:50px 50px 50px 50px;

Ce que je reçois:
What I get with margin:50px 50px 50px 50px;

Code:

#outer {
        width: 500px; 
        height: 200px; 
        background: #FFCCCC;
        margin: 50px auto 0 auto;
        display: block;
}
#inner {
        background: #FFCC33;
        margin: 50px 50px 50px 50px;
        padding: 10px;
        display: block;
}
<div id="outer">
  <div id="inner">
        Hello world!
  </div>
</div>

W3Schools n’expliquez pas pourquoi la marge se comporte de cette façon.

300
jamietelin

Vous voyez en fait la marge supérieure de l’élément #innerréduire dans le bord supérieur de l’élément #outer, ne laissant que la marge #outer intacte (mais pas montré dans vos images). Les bords supérieurs des deux boîtes sont alignés les uns sur les autres car leurs marges sont égales.

Voici les points pertinents de la spécification W3C:

8.3.1 Réduire les marges

En CSS, les marges adjacentes de deux boîtes ou plus (qui peuvent être ou non des frères et sœurs) peuvent être combinées pour former une seule marge. Les marges qui se combinent de cette manière sont dites s'effondrer , et la marge combinée résultante est appelée une marge effondrée .

Les marges verticales adjacentes s'effondrent [...]

Deux marges sont adjacentes si et seulement si:

  • les deux appartiennent à des blocs de flux entrants qui participent au même contexte de formatage de bloc
  • pas de boîtes de lignes, pas de dégagement, pas de rembourrage et aucune bordure ne les sépare
  • les deux appartiennent à des bords de boîtes adjacents verticalement, c'est-à-dire forment l'une des paires suivantes:
    • la marge supérieure d'une boîte et la marge supérieure de son premier enfant entrant

La raison pour laquelle l’une des opérations suivantes empêche la marge de s’effondrer:

Est-ce parce que:

  • Les marges entre une boîte flottante et toute autre boîte ne s'effondrent pas (même entre un flottant et ses enfants entrants).
  • Les marges des éléments qui établissent de nouveaux contextes de formatage de bloc (tels que des éléments flottants et des éléments avec un "dépassement de capacité" autre que "visible") ne sont pas réduites à l'aide de leurs enfants entrants.
  • Les marges des blocs en-ligne ne s'effondrent pas (même avec leurs enfants dans le flux).

Les marges gauche et droite se comportent comme prévu:

Les marges horizontales ne s'effondrent jamais.

425
BoltClock

Essayez d’utiliser display: inline-block; sur la div interne.

#outer {
    width:500px; 
    height:200px; 
    background:#FFCCCC;
    margin:50px auto 0 auto;
    display:block;
}
#inner {
    background:#FFCC33;
    margin:50px 50px 50px 50px;
    padding:10px;
    display:inline-block;
}
82
enderskill

Ce que @ BoltClock a mentionné est plutôt solide. Et ici, je veux juste ajouter plusieurs solutions supplémentaires à ce problème. vérifiez ceci w3c_collapsing margin . Les parties vertes représentent le potentiel de résolution de ce problème.

Solution 1

Les marges entre une boîte flottante et toute autre boîte ne s'effondrent pas (même entre un flottant et ses enfants entrants).

cela signifie que je peux ajouter float:left à #outer ou #innerdemo1 .

notez également que float invaliderait le auto dans la marge.

Solution 2

Les marges des éléments qui établissent de nouveaux contextes de formatage de bloc (tels que des éléments flottants et des éléments avec un "dépassement de capacité" autre que "visible") ne sont pas réduites à l'aide de leurs enfants entrants.

autre que visible, plaçons overflow: hidden dans #outer. Et cette voie semble assez simple et décente. Je l'aime.

#outer{
    width: 500px;
    height: 200px;
    background: #FFCCCC;
    margin: 50px auto;
    overflow: hidden;
}
#inner {
    background: #FFCC33;
    height: 50px;
    margin: 50px;
}

Solution 3

Les marges des boîtes en position absolue ne s'effondrent pas (même avec leurs enfants entrants).

#outer{
    width: 500px;
    height: 200px;
    background: #FFCCCC;
    margin: 50px auto;
    position: absolute; 
}
#inner{
    background: #FFCC33;
    height: 50px;
    margin: 50px;
}

ou

#outer{
    width: 500px;
    height: 200px;
    background: #FFCCCC;
    margin: 50px auto;
    position: relative; 
}
#inner {
    background: #FFCC33;
    height: 50px;
    margin: 50px;
    position: absolute;
}

ces deux méthodes vont briser le flux normal de div

Solution 4

Les marges des blocs en-ligne ne s'effondrent pas (même avec leurs enfants dans le flux).

est le même que @enderskill

Solution 5

La marge inférieure d'un élément de niveau bloc en entrée se réduit toujours avec la marge supérieure de son prochain frère au niveau bloc en entrée, à moins que ce dernier ne dispose de l'autorisation nécessaire.

Cela n’a pas beaucoup de travail à faire avec la question puisque c’est la marge qui s’effondre entre frères et soeurs. cela signifie généralement que si une boîte supérieure a margin-bottom: 30px et qu'une boîte-sœur a margin-top: 10px. La marge totale entre eux est 30px au lieu de 40px.

Solution 6

La marge supérieure d'un élément de bloc entrant dans le flux se réduit avec la première marge supérieure de son enfant au niveau du bloc entrant dans le flux si l'élément n'a pas de bordure supérieure, pas de remplissage supérieur et si l'enfant n'a pas de marge.

C'est très intéressant et je peux juste ajouter une ligne de bordure supérieure

#outer{
    width: 500px;
    height: 200px;
    background: #FFCCCC;
    margin: 50px auto;
    border-top: 1px solid red;

}
#inner {
    background: #FFCC33;
    height: 50px;
    margin: 50px;

}

De plus, <div> est au niveau du bloc par défaut, vous n'avez donc pas à le déclarer exprès. Désolé de ne pas pouvoir poster plus de 2 liens et images en raison de ma réputation de novice. Au moins, vous savez d'où vient le problème la prochaine fois que vous voyez quelque chose de similaire.

19
Qiang

Vous ne savez pas pourquoi ce que vous avez ne fonctionne pas, mais vous pouvez ajouter

overflow: auto;

à la div externe.

12
Brandon

Pas exactement pourquoi, mais changer le CSS interne en

display:inline-block;

semble fonctionner;

10
harriyott

Si vous ajoutez un remplissage à #outer, cela fonctionne.

démo

#outer {
    width:500px; 
    height:200px; 
    background:#FFCCCC;
    margin:50px auto 0 auto;
    display:block;
    padding-top:1px;
}
10
bookcasey

Ne répond pas au "pourquoi" (doit être quelque chose avec la marge de réduction), mais semble être le moyen le plus simple/logique de faire ce que vous essayez de faire, c'est juste ajoutez padding-top à la division externe :

http://jsfiddle.net/hpU5d/1/

Remarque mineure - il ne devrait pas être nécessaire de définir un div sur display:block; sauf si votre code indique quelque chose d'autre qui ne le bloque pas.

2
Dave

essaye ça:

#outer {
    width:500px; 
    height:200px; 
    background:#FFCCCC;
    margin:50px auto 0 auto;
    display:table;
}
#inner {
    background:#FFCC33;
    margin:50px 50px 50px 50px;
    padding:10px;
    display:block;
}​

http://jsfiddle.net/7AXTf/

Bonne chance

2
Mustafa M Jalal

Je suppose que définir la propriété position de # inner div en relatif peut également aider à obtenir cet effet. Quoi qu'il en soit, j'ai essayé le code original collé dans la question sur IE9 et le dernier Google Chrome et ils donnent déjà l'effet souhaité sans aucune modification.

1
viditkothari

Utilisez padding-top:50pxpour div externe. Quelque chose comme ça:

#outer {
    width:500px; 
    height:200px; 
    background:#FFCCCC;
    margin:50px auto 0 auto;
    display:table;}

Remarque: le rembourrage augmentera la taille de votre div. Dans ce cas, si la taille de votre div est importante, je veux dire si elle doit avoir une hauteur spécifique. diminuer la hauteur de 50px .:

#outer {
    width:500px; 
    height:150px; 
    background:#FFCCCC;
    margin:50px auto 0 auto;
    display:table;}
1
Ata Iravani

Avez-vous essayé! Important avant tout, ça va forcer tout:

margin:50px 50px 50px 50px !important;
0
atgr24869

Juste pour une solution rapide, essayez d’envelopper vos éléments enfants dans un élément div comme celui-ci -

<div id="outer">
   <div class="divadjust" style="padding-top: 1px">
      <div id="inner">
         Hello world!
      </div>
   </div>
</div>

La marge de inner div ne sera pas réduite en raison du remplissage de 1px entre outer et inner div. Donc logiquement, vous aurez 1px un espace supplémentaire avec la marge existante de inner div.

0
Mithilesh Tipkari