Pourquoi cet élément de bloc en ligne est-il poussé vers le bas?

238

Voici mon code et je veux comprendre pourquoi #firstDiv est poussé vers le bas par tous les navigateurs. Je veux vraiment comprendre le fonctionnement interne du fait que pourquoi il est poussé vers le bas plutôt que de le tirer vers le haut d'une manière ou d'une autre. (et je sais comment aligner leurs sommets :))

Et je sais que son débordement: caché ce qui le provoque mais pas sûr que pourquoi il pousse ce div vers le bas.

body {
  width: 350px;
  margin: 0px auto;
}

#container {
  border: 15px solid orange;
}

#firstDiv {
  border: 10px solid brown;
  display: inline-block;
  width: 70px;
  overflow: hidden;
}

#secondDiv {
  border: 10px solid skyblue;
  float: left;
  width: 70px;
}

#thirdDiv {
  display: inline-block;
  border: 5px solid yellowgreen;
}
<div id="container">
  <div id="firstDiv">FIRST</div>
  <div id="secondDiv">SECOND</div>
  <div id="thirdDiv">THIRD
    <br>some more content<br> some more content
  </div>
</div>

http://jsfiddle.net/WGCyu/ .

Shawn Taylor
la source

Réponses:

361

Fondamentalement, vous avez ajouté plus d'encombrement dans votre code, ce qui crée plus de confusion, donc j'essaie d'abord de supprimer l'encombrement qui empêche de comprendre le vrai problème.

Tout d'abord, nous devons établir que quelle est la vraie question? C'est pour cela que l' inline-blockélément " " est poussé vers le bas.

Maintenant, nous commençons à le comprendre et à éliminer le désordre en premier.

1 - Pourquoi ne pas donner aux trois div la même largeur de bordure? Donnons-le.

2 - L'élément flottant a-t - il un lien avec l'élément de bloc en ligne poussé vers le bas? Non, cela n'a rien à voir avec ça.

Nous avons donc complètement supprimé cette division . Et vous êtes témoin du même comportement d'élément de bloc en ligne poussé vers le bas.

Voici le tour de la littérature pour saisir l'idée des boîtes de ligne et comment elles sont alignées sur la même ligne, surtout lisez attentivement le dernier paragraphe car c'est là que réside la réponse à votre question.

La ligne de base d'un "bloc en ligne" est la ligne de base de sa dernière boîte de ligne dans le flux normal, sauf si elle n'a pas de boîtes de ligne en flux ou si sa propriété "overflow" a une valeur calculée autre que "visible", dans auquel cas la ligne de base est le bord inférieur de la marge.

Si vous n'êtes pas sûr de la base, voici une brève explication en termes simples.

Tous les caractères sauf «gjpqy» sont écrits sur la ligne de base, vous pouvez penser à la ligne de base comme si vous dessiniez une simple ligne horizontale identique à celle soulignée juste en dessous de ces «caractères aléatoires», alors ce sera la ligne de base mais maintenant si vous écrivez l'un des «gjpqy» caractère (s) sur la même ligne puis la partie inférieure de ces caractères tomberait en dessous de la ligne.

Donc, nous pouvons dire que tous les caractères à l'exception de «gjpqy» sont écrits complètement au-dessus de la ligne de base tandis qu'une partie de ces caractères est écrite en dessous de la ligne de base.

3 - Pourquoi ne pas vérifier où se situe la ligne de base de notre ligne? J'ai ajouté quelques caractères qui montrent la ligne de base de notre ligne.

4 - Pourquoi ne pas ajouter aussi des personnages dans nos divs pour trouver leurs références dans les div? Ici, certains caractères ajoutés dans les divs pour clarifier la ligne de base .

Maintenant, lorsque vous comprenez la ligne de base, lisez la version simplifiée suivante sur la ligne de base des blocs en ligne.

i) Si le bloc en ligne en question a sa propriété de débordement définie sur visible (ce qui est par défaut, il n'est donc pas nécessaire de le définir). Alors sa ligne de base serait la ligne de base du bloc conteneur de la ligne.

ii) Si le bloc en ligne en question a sa propriété de débordement définie sur AUTRE QUE visible. Ensuite, sa marge inférieure serait sur la ligne de base de la ligne de la boîte contenant.

  • Premier point en détail

Maintenant, regardez à nouveau pour clarifier votre concept que ce qui se passe avec la div verte . En cas de confusion, des caractères sont ajoutés à proximité de la division verte pour établir la ligne de base du bloc contenant et la ligne de base de la division verte est alignée.

Eh bien, je prétends maintenant qu'ils ont la même base de référence? DROITE?

5 - Alors pourquoi ne pas les superposer et voir s'ils sont bien ajustés les uns aux autres? Donc, j'apporte le troisième div à gauche: 35px; pour vérifier s'ils ont la même ligne de base maintenant ?

Maintenant, nous avons fait prouver notre premier point.

  • Deuxième point en détail

Eh bien, après l'explication du premier point, le deuxième point est facilement digestible et vous voyez que le premier div qui a une propriété de débordement définie sur autre que visible (caché) a sa marge inférieure sur la ligne de base de la ligne.

Maintenant, vous pouvez faire quelques expériences pour l'illustrer davantage.

  1. Définissez le premier débordement div: visible (ou supprimez-le complètement) .
  2. Définir le deuxième débordement div: autre que visible .
  3. Définissez le débordement des deux divs: autre que visible .

Maintenant, ramenez votre fouillis et voyez si tout va bien pour vous.

  1. Ramenez votre div flotté (bien sûr, il est nécessaire d'
    augmenter une certaine largeur du corps) Vous voyez que cela n'a aucun effet.
  2. Ramenez les mêmes marges impaires .
  3. Réglez le div vert sur le débordement: visible lorsque vous définissez votre question (ce désalignement est dû à l'augmentation de la largeur de la bordure de 1px à 5px, donc si vous ajustez la gauche à gauche, vous verrez qu'il n'y a pas de problème)
  4. Supprimez maintenant les caractères supplémentaires que j'ai ajoutés pour faciliter la compréhension . (et bien sûr, supprimez le négatif à gauche)
  5. Enfin, réduisez la largeur du corps car nous n'en avons plus besoin de plus large.

Et maintenant, nous revenons à notre point de départ.

J'espère avoir répondu à votre question.

Gary Lindahl
la source
1
Merci pour cette excellente explication, mais je n'ai pas compris votre point de vue "Alors sa ligne de base serait la ligne de base du bloc contenant la ligne." Est-ce la même chose que la ligne de base de la ligne comme vous l'avez précisé au deuxième point?
Shawn Taylor
2
Réponse tardive. Je viens de noter le même problème, et je voulais juste remercier Gary Lindahl pour l'explication NICE.
TimSPQR
+1 ntgCleaner Même si j'apprécie les bonnes réponses, Gary Lindahl est tellement à lire et il me manque juste ces quelques lignes où il est dit 'Solution: XY'
Basic Coder
J'ai trouvé cette explication détaillée incroyablement informative, merci. J'ai eu du mal avec un concept pendant un certain temps et j'ai créé un violon mis à jour qui pourrait clarifier pour d'autres.
jonsanders101
@ntgCleaner merci man .. même après toutes les explications, je n'ai pas pu le faire fonctionner. mais votre commentaire l'a fait :)
supersan
330

La valeur par défaut vertical-alignen CSS est baseline& cette règle s'applique également à la inline-blocklecture de ce http://www.brunildo.org/test/inline-block.html

Écrivez vertical-align:topdans votre inline-blockDIV.

Consultez ce http://jsfiddle.net/WGCyu/1/

sandeep
la source
3
Avez-vous lu ma question? Je n'ai jamais demandé de corriger le problème.
Shawn Taylor
23
@ShawnTaylor: Le titre de la question est très trompeur. Nous lisons instinctivement le titre puis visons le code, s'il y en a. Nous lisons rarement le texte réel. C'est une mauvaise habitude mais vous devez probablement comprendre pourquoi cela se produit. : P
Purag
@sandeep: concernant votre modification, alors pourquoi firstDiv est aligné en haut même lorsque l'alignement vertical en est supprimé
Shawn Taylor
@sandeep: Le lien que vous avez fourni est informatif, mais il n'aide pas sur cette question car il ne décrit pas le comportement de display:inline-blockcombiné avec float:left/right.
Zeta
2
@ThomasMcCabe Hardly; si quelqu'un publie une mauvaise réponse, elle mérite d'être déclassée pour signaler aux futurs téléspectateurs qu'il y a quelque chose qui ne va pas, indépendamment de leurs bonnes intentions. Cela dit, je ne pense pas que cette réponse ait jamais mérité un vote négatif; même dans sa forme originale, il a fourni une pièce clé du puzzle omise par la réponse acceptée - que l'alignement de la ligne de base n'est pas le seul moyen d'alignement vertical des éléments, et que si vous changez la vertical-alignpropriété, aucune de la complexité décrite dans le la réponse acceptée s'applique.
Mark Amery
9

Consultez cet exemple alternatif. La raison d'un tel comportement est décrite dans le module CSS3: ligne: 3.2. Habillage de la boîte de ligne [1] :

En général, le bord de début d'une zone de ligne touche le bord de début de son bloc conteneur et le bord de fin touche le bord de fin de son bloc conteneur. Cependant, des boîtes flottantes peuvent se trouver entre le bord du bloc contenant et le bord de la boîte de ligne. Ainsi, bien que les boîtes de ligne dans le même contexte de mise en forme en ligne aient généralement la même avance de progression en ligne (celle du bloc contenant), elles peuvent varier si l'espace de progression en ligne disponible est réduit en raison des flottants [...]

Comme vous pouvez le voir, le troisième élément est poussé vers le bas, bien qu'il n'ait pas de overflowpropriété. La raison doit être ailleurs. Le deuxième comportement que vous remarquez est décrit dans les feuilles de style en cascade, niveau 2, révision 1 (CSS 2.1): 9.5 Flotteurs [2] :

Puisqu'un flottant n'est pas dans le flux, les blocs de blocs non positionnés créés avant et après le flotteur circulent verticalement comme si le flotteur n'existait pas. Toutefois, les zones de ligne actuelles et suivantes créées à côté du flottant sont raccourcies si nécessaire pour faire de la place à la zone de marge du flottant.

Tous vos display:inline-block;divs utilisent un type spécial de baselinedans ce cas 10.8 Calculs de hauteur de ligne: les propriétés 'line-height' et 'vertical-align' (très fin) [3] :

La ligne de base d'un "bloc en ligne" est la ligne de base de sa dernière boîte de ligne dans le flux normal, sauf si elle n'a pas de boîtes de ligne en flux ou si sa propriété "overflow" a une valeur calculée autre que "visible", dans auquel cas la ligne de base est le bord inférieur de la marge.

Ainsi, lorsque vous utilisez des éléments flottants et des inline-blockéléments, l'élément flottant sera poussé sur le côté et le formatage en ligne sera recalculé selon 1 . D'un autre côté, les éléments suivants sont raccourcis s'ils ne correspondent pas. Puisque vous travaillez déjà avec un minimum d'espace, il n'y a pas d'autre moyen de modifier vos éléments que de les pousser 2 . Dans ce cas, l'élément le plus élevé définira la taille de votre div enveloppante, définissant ainsi le baseline 3 , tandis que d'autre part la modification de position et de largeur indiquée en 2 ne peut pas être appliquée à de tels éléments de hauteur maximale espacée minimale. Dans ce cas, un comportement comme dans ma toute première démo en résultera.

Enfin, la raison pour laquelle vous overflow:hiddenempêcherez #firstDivd'être poussé vers le bord inférieur de votre #container, même si je n'ai pas trouvé de raison dans la section 11 . Sans overflow:hiddencela fonctionne comme excepté et défini par 2 et 3 . Démo

TL; DR: Examinez de très près les recommandations W3 et les implémentations dans le navigateur. À mon humble avis, les éléments flottants sont déterminés à montrer un comportement inattendu si vous ne connaissez pas tous les changements qu'ils apportent aux éléments environnants. Voici une autre démo qui montre un problème commun avec les flotteurs.

Zeta
la source
3
Ce "standard" est un gâchis incroyable. C'est incroyable qu'ils aient pu faire en sorte que ces choses se comportent de manière cohérente entre les navigateurs. Oh, attends, non, ils n'ont jamais pu faire ça.
Triynko
6

À l'origine, j'ai commencé à répondre à cette question , mais elle a été verrouillée en tant que dupe avant de pouvoir terminer, alors je poste la réponse ici à la place.

Tout d'abord, nous devons comprendre ce qui inline-blockest.
La définition dans MDN dit:

L'élément génère une boîte d'élément de bloc qui sera diffusée avec le contenu environnant comme s'il s'agissait d'une seule boîte en ligne (se comportant un peu comme le ferait un élément remplacé)

Pour comprendre ce qui se passe ici, nous devons regarder vertical-align, et c'est la valeur par défaut baseline.

visualisations de position verticale
Dans cette illustration, vous avez ce nuancier:
Bleu: La ligne de base
Rouge: Le haut et le bas de la hauteur de ligne
Vert: Le haut et le bas de la zone de contenu en ligne.

Dans l'élément #left, vous avez du contenu textuel qui contrôle quelle est la ligne de base. Cela signifie que le texte à l'intérieur définit la ligne de base pour #left.
Dans le #right, il n'y a pas de contenu, donc le navigateur n'a pas d'autre option que d'utiliser le bas de la boîte comme ligne de base.

Voir cette visualisation où j'ai dessiné la ligne de base sur un exemple où le premier conteneur en ligne a du texte et le suivant est vide:

Ligne de base dessinée

Si vous alignez spécifiquement un élément sur le dessus, vous dites vraiment que vous alignez le haut de cet élément sur le haut de la zone de ligne.

Cela pourrait être plus facile à comprendre par un exemple.

div {
    display: inline-block;
    width: 100px;
    height: 150px;
    background: gray;
    vertical-align: baseline;
}
div#middle {
    vertical-align: top;
    height: 50px
}
   
div#right {
    font-size: 30px;
    height: 100px
}
<div id="left">
  <span>groovy</span>
</div>
<div id="middle">groovy</div>

<div id="right">groovy</div>

Le résultat est le suivant - et j'ai ajouté la ligne de base bleue et la zone de ligne rouge: ce qui se passe ici, c'est que la hauteur de la zone de ligne dépend de la façon dont le contenu de la ligne entière est disposé. Cela signifie que pour calculer l'alignement supérieur, les alignements de ligne de base doivent être calculés en premier. L' élément a , donc ce n'est pas utilisé pour le positionnement de la ligne de base. mais les et sont positionnés verticalement de sorte que leurs lignes de base soient alignées. Lorsque cela est fait, la hauteur de la zone de ligne a augmenté, car l' élément a été légèrement poussé en raison de la taille de police plus grande. Ensuite, la position supérieure de l' élément peut être calculée, et ce le long du haut de la zone de ligne.Alignement vertical expliqué
#middlevertical-align:top#left#right#right#middle

admiration
la source
1

le problème est que vous avez appliqué float: à gauche sur la deuxième div. ce qui fait que le deuxième div vient sur le côté gauche et votre premier div tombe et vient après votre deuxième div. Si vous appliquez float: à gauche sur le premier div également, votre problème aura disparu.

débordement: caché ne cause aucun problème à votre mise en page, débordement: caché affecte uniquement les éléments internes d'une div, il n'a rien à voir avec d'autres éléments qui sont à l'extérieur.

Pal Singh
la source
Eh bien, si c'est poussé parce qu'il vient en deuxième position après la division flottante, alors pourquoi ThirdDiv ne descend pas?
Shawn Taylor
parce que le troisième div a un deuxième div avant qui n'a pas de flotteur: gauche;
Pal Singh
Mais où est mentionnée cette règle selon laquelle si un div viendra après le div flottant, il baissera? J'ai vérifié w3.org.
Shawn Taylor
l'élément qui n'est pas flottant tombe à la ligne de base et si vous avez fait un vote négatif, je dois dire que c'était la réponse la plus logique
Pal Singh
Non, je n'ai pas voté négatif et oui votre réponse ne mérite pas d'être négative. Je viens de voter à la hausse.
Shawn Taylor
0

Essayez d'ajouter padding:0;au corps et de supprimer la marge de vos divs.

Ajoutez de la background-color:*anycouleur à l'arrière-plan * pour vérifier la différence.

LOLZ
la source
Modifiez la réponse pour formater le code. Vous pouvez formater le code en ajoutant le symbole `avant de commencer le code et après avoir terminé le code. comme codepar exemple:. background-color:any color
JINO SHAJI
0

Essayez de rendre toutes les propriétés CSS de tous les éléments identiques.

J'ai eu un problème similaire et en résolvant cela, j'ai identifié que je déposais un élément avec la propriété Font dans l'élément Div.

Après avoir supprimé cet élément avec la propriété Font, l'alignement de tous les DIV a été perturbé. Pour résoudre ce problème, j'ai défini la propriété Font sur tous les éléments DIV de la même manière que l'élément qui y est déposé.

Dans l'exemple suivant, l'élément Dropped de la classe ".dldCuboidButton" défini avec la taille de police: 30 px.

J'ai donc ajouté la même propriété aux classes restantes, à savoir .cuboidRecycle, .liCollect, .dldCollect qui sont utilisées par les éléments DIV. De cette façon, tous les éléments DIV suivent les mêmes mesures avant et après y avoir déposé l'élément.

.cuboidRecycle {
    height:40px; 
    width:'20px; float:right';
    overflow:'none';
    background-color:#cab287;
    color:#ffffff; 
    border-radius:8px; 
    text-align:'center'; 
    vertical-align:'top';
    display: inline-block;
    font-size: 30px; /* Set a font-size */
}


.liCollect {
    height:40px; 
    width:'20px; float:right';
    overflow:'none';
    background-color:#cab287;
    color:#ffffff; 
    border-radius:8px; 
    text-align:'center'; 
    vertical-align:'top';
    display: inline-block;
    font-size: 30px; /* Set a font-size */
}

.dldCollect {
    height:40px; 
    width:'20px; float:right';
    overflow:'none';
    background-color:#009933;
    color:#ffffff; 
    border-radius:8px; 
    text-align:'center'; 
    vertical-align:'top';
    display: inline-block;
    font-size: 30px; /* Set a font-size */
}


.dldCuboidButton {
    background-color:  #7c6436;
    color: white; /* White text */
    font-size: 30px; /* Set a font-size */
    border-radius: 8px;
    margin-top: 1px;
  }

Voici l'exemple de HTML créé dynamiquement à l'aide de CSS ci-dessus.

$("div#tabs").append(
  "<div id='" + newTabId + "'>#" + uniqueId + 
  "<input type=hidden id=hdn_tmsource_" + uniqueId + "  value='" + divTmpfest + "'>" + 
  "<input type=hidden id=leCuboidInfo_" + uniqueId + " value=''>" + 
  "<div id='" + divRecycleCuboid + "' class=cuboidRecycle ondrop='removeDraggedCuboids(event, ui)'  ondragover='allowDrop(event)'><font size='1' color='red'> Trash bin </font></div>" +
  "<div id='" + divDropLeCuboid  + "' class=liCollect ondrop='dropForLinkExport(event)'  ondragover='allowDrop(event)'><font size='1' color='red'>Drop Template Manifest Cuboid here</font></div>" +
  "<div id='" + divDropDwldCuboid  + "' class=dldCollect ondrop='dropForTMEntry(event)'  ondragover='allowDrop(event)'><font size='1' color='red'>Drop Template Cuboids here..</font></div>" +
  "</div>" 
);
Rahul Varadkar
la source