web-dev-qa-db-fra.com

La marge sur l'élément enfant déplace l'élément parent

J'ai un div (parent) qui contient un autre div (enfant). Parent est le premier élément de body sans style CSS particulier. Quand je mis

.child
{
    margin-top: 10px;
}

Le résultat final est que le sommet de mon enfant est toujours aligné avec le parent. Au lieu que l'enfant soit décalé de 10 pixels vers le bas, mon parent baisse de 10 pixels.

Mon DOCTYPE est réglé sur XHTML Transitional.

Qu'est-ce qui me manque ici?

éditez 1
Mes parents doivent avoir des dimensions strictement définies, car leur arrière-plan doit être affiché en dessous (pixels parfaits). Donc, définir des marges verticales est un no go.

éditer 2
Ce comportement est le même sur FF, IE ainsi que sur CR.

374
Robert Koritnik

Vous avez trouvé une alternative à Éléments enfants avec des marges dans des DIV Vous pouvez également ajouter:

.parent { overflow: auto; }

ou:

.parent { overflow: hidden; }

Cela empêche les marges de réduire . La bordure et le rembourrage font la même chose. Par conséquent, vous pouvez également utiliser les éléments suivants pour empêcher un repli dans la marge supérieure:

.parent {
    padding-top: 1px;
    margin-top: -1px;
}

Mise à jour à la demande générale: L'intérêt de réduire les marges est de gérer le contenu textuel. Par exemple:

<style type="text/css">
    h1, h2, p, ul {
        margin-top: 1em;
        margin-bottom: 1em;
    }
</style>

<h1>Title!</h1>
<div class="text">
    <h2>Title!</h2>
    <p>Paragraph</p>
</div>
<div class="text">
    <h2>Title!</h2>
    <p>Paragraph</p>
    <ul>
        <li>list item</li>
    </ul>
</div>

Étant donné que le navigateur réduit les marges, le texte s'affichera comme prévu et les balises wrapper <div> n'influencent pas les marges. Chaque élément garantit un espacement autour de celui-ci, mais cet espacement ne sera pas doublé. Les marges de <h2> et <p> ne s'additionnent pas, mais se glissent l'une dans l'autre (elles se réduisent). Il en va de même pour les éléments <p> et <ul>.

Malheureusement, avec les conceptions modernes, cette idée peut vous mordre lorsque vous voulez explicitement un conteneur. Cela s'appelle un nouveau contexte de formatage de bloc en langage CSS. L'astuce overflow ou la marge vous le donnera.

443
vdboor

C'est un comportement normal (au moins parmi les implémentations de navigateur). La marge n'affecte pas la position de l'enfant par rapport à son parent, sauf si le parent dispose d'un remplissage, auquel cas la plupart des navigateurs ajouteront alors la marge de l'enfant au remplissage du parent.

Pour obtenir le comportement souhaité, il vous faut:

.child {
    margin-top: 0;
}

.parent {
    padding-top: 10px;
}
46
Ben James

Bien que toutes les réponses résolvent le problème mais qu’elles viennent avec des compromis/ajustements/compromis comme

  • floats, vous avez pour faire flotter des éléments
  • border-top, Ceci repousse le parent d'au moins 1px vers le bas, ce qui devrait alors être ajusté en introduisant la marge -1px dans l'élément parent lui-même. Cela peut créer des problèmes lorsque le parent a déjà margin-top en unités relatives.
  • padding-top, même effet que border-top
  • overflow: hidden, Ne peut pas être utilisé lorsque le parent doit afficher le contenu en débordement, comme un menu déroulant.
  • overflow: auto, Introduit des barres de défilement pour l'élément parent qui a (intentionnellement) un contenu débordant (comme les ombres ou le triangle de l'info-bulle)

Le problème peut être résolu en utilisant les pseudo-éléments CSS3 comme suit

.parent::before {
  clear: both;
  content: "";
  display: table;
  margin-top: -1px;
  height: 0;
}

https://jsfiddle.net/hLgbyax5/1/

19
Ejaz

ajoute le style display:inline-block à l'élément enfant

l'élément parent ne doit pas être vide au moins mettre &nbsp; avant l'élément enfant.

7
George SEDRA

C'est ce qui a fonctionné pour moi

.parent {
padding-top: 1px;
margin-top: -1px;
}

.child {
margin-top:260px;
}

http://jsfiddle.net/97fzwuxh/

6
erdomester

Je découvre que, dans votre .css> si vous définissez la propriété d'affichage d'un élément div en inline-block ça corrige le problème. et la marge fonctionnera comme prévu.

2
vincent thorpe

J’avais aussi ce problème, mais j’ai préféré éviter les hacks à marges négatives, alors j’ai mis un

<div class="supercontainer"></div>

autour de tout cela qui a des rembourrages au lieu de marges. Bien sûr, cela signifie plus de divitis, mais c'est probablement le moyen le plus propre de le faire correctement.

1
Zyl

Une solution alternative que j'ai trouvée avant de connaître la bonne réponse consistait à ajouter un bordure transparente à l'élément parent.

Votre boîte utilisera des pixels supplémentaires si ...

.parent {
    border:1px solid transparent;
}
1
SandRock

Solution soignée en CSS uniquement

Utilisez le code suivant pour ajouter un premier enfant sans contenu au div qui se déplace involontairement:

.parent:before
{content: '';position: relative;height: 0px;width: 0px;overflow: hidden;white-space: pre;}

L'avantage de cette méthode est qu'il n'est pas nécessaire de modifier le code CSS d'un élément existant et a donc un impact minimal sur la conception. A côté de cela, l'élément ajouté est un pseudo-élément, qui est not dans l'arborescence DOM.

Les pseudo-éléments sont largement pris en charge: Firefox 3+, Safari 3+, Chrome 3+, Opera 10+ et IE 8+. Cela fonctionnera dans n'importe quel navigateur moderne (soyez prudent avec le plus récent ::before, qui n'est pas pris en charge dans IE8).

Le contexte

Si le premier enfant d'un élément a un margin-top, le parent ajustera sa position afin de réduire les marges redondantes. Pourquoi? C'est juste comme ça.

Compte tenu du problème suivant:

<style type="text/css">
div {position: relative;}
.parent {background-color: #ccc;}
.child {margin-top: 40px;}
</style>

<div class="parent"><!--This div moves 40px too-->
    <div class="child">Hello world!</div>
</div>

Vous pouvez y remédier en ajoutant un enfant avec un contenu, tel qu'un simple espace. Mais nous n'aimons pas tous ajouter des espaces pour ce qui est un problème de conception uniquement. Par conséquent, utilisez la propriété white-space pour simuler du contenu.

<style type="text/css">
div {position: relative;}
.parent {background-color: #ccc;}
.child {margin-top: 40px;}
.fix {position: relative;white-space: pre;height: 0px;width: 0px;overflow: hidden;}
</style>

<div class="parent"><!--This div won't move anymore-->
    <div class="fix"></div>
    <div class="child">Hello world!</div>
</div>

position: relative; garantit le positionnement correct du correctif. Et white-space: pre; vous évite de devoir ajouter du contenu - comme un espace blanc - au correctif. Et height: 0px;width: 0px;overflow: hidden; s'assure que vous ne verrez jamais le correctif.

Vous devrez peut-être ajouter line-height: 0px; ou max-height: 0px; pour vous assurer que la hauteur est réellement nulle dans les anciens navigateurs IE (je ne suis pas sûr). Et vous pouvez éventuellement y ajouter <!--dummy--> dans les anciens navigateurs IE, si cela ne fonctionne pas.

En bref, vous pouvez faire tout cela uniquement avec CSS (ce qui vous évite d’ajouter un enfant à l’arborescence DOM HTML):

<style type="text/css">
div {position: relative;}
.parent {background-color: #ccc;}
.child {margin-top: 40px;}

.parent:before {content: '';position: relative;height: 0px;width: 0px;overflow: hidden;white-space: pre;}
</style>

<div class="parent"><!--This div won't move anymore-->
    <div class="child">Hello world!</div>
</div>
1
Yeti

fait intéressant, ma solution préférée à ce problème n’est pas encore mentionnée ici: utiliser des flotteurs.

html:

<div class="parent">
    <div class="child"></div>
</div>

css:

.parent{width:100px; height:100px;}
.child{float:left; margin-top:20px; width:50px; height:50px;}

voir ici: http://codepen.io/anon/pen/Iphol

notez que si vous avez besoin de hauteur dynamique sur le parent, il doit également flotter. Il vous suffit donc de remplacer height:100px; par float:left;

1
schellmax

Les margin des éléments contenus dans .child sont en train de s'effondrer.

<html>
<style type="text/css" media="screen">
    #parent {background:#dadada;}
    #child {background:red; margin-top:17px;}
</style>
<body>
<div id="parent">

    <p>&amp;</p>

    <div id="child">
        <p>&amp;</p>    
    </div>

</div>
</body>
</html>

Dans cet exemple, p reçoit un margin des styles par défaut du navigateur. La valeur par défaut du navigateur font-size est généralement de 16 pixels. En ayant un margin-top de plus de 16 px sur #child, vous commencez à remarquer un changement de position.

1
25thhour

Pour empêcher le "parent div", utilisez la marge de "div enfant":
En parent, utilisez ces css:

  • Float
  • Rembourrage
  • Frontière
  • Débordement
0
bingo

Utiliser top au lieu de margin-top est une autre solution possible, le cas échéant.

0
lamplightdev