¿Por qué este elemento de bloque en línea se empuja hacia abajo?

238

El siguiente es mi código y quiero entender por qué #firstDiv está siendo empujado hacia abajo por todos los navegadores. Realmente quiero entender el funcionamiento interno del hecho de que se está empujando hacia abajo en lugar de tirar hacia arriba de una manera u otra. (y sé cómo alinear sus tops :))

Y sé que está desbordado: oculto, lo que lo está causando, pero no estoy seguro de por qué está empujando ese div hacia abajo.

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
fuente

Respuestas:

361

Básicamente, ha agregado más desorden en su código, lo que está creando más confusión, así que primero trato de eliminar el desorden que dificulta la comprensión del problema real.

Antes que nada tenemos que establecer que ¿cuál es la verdadera pregunta? Es por eso que el " inline-block" elemento es empujado hacia abajo.

Ahora comenzamos a entenderlo y eliminamos el desorden primero.

1 - ¿Por qué no dar a los tres divs el mismo ancho de borde? Vamos a darlo.

2 - ¿El elemento flotante tiene alguna conexión con el elemento de bloque en línea que se empuja hacia abajo? No, no tiene nada que ver con eso.

Entonces, hemos eliminado ese div por completo . Y está presenciando el mismo comportamiento del elemento de bloque en línea empujado hacia abajo.

Aquí llega el turno de un poco de literatura para comprender la idea de los cuadros de línea y cómo están alineados en la misma línea, especialmente leer el último párrafo cuidadosamente porque ahí está la respuesta a su pregunta.

La línea base de un 'bloque en línea' es la línea base de su último cuadro de línea en el flujo normal, a menos que no tenga cuadros de línea en flujo o si su propiedad 'desbordamiento' tiene un valor calculado distinto de 'visible', en en cuyo caso la línea de base es el borde del margen inferior.

Si no está seguro acerca de la línea de base , aquí hay una breve explicación en palabras simples.

Todos los caracteres, excepto 'gjpqy', están escritos en la línea de base. Puede pensar en la línea de base como si dibujara una línea horizontal simple igual que subrayando justo debajo de estos "caracteres aleatorios", entonces será la línea de base, pero ahora si escribe cualquiera de 'gjpqy' los caracteres en la misma línea y luego la parte inferior de estos caracteres caerían debajo de la línea.

Entonces, podemos decir que todos los caracteres, excepto 'gjpqy', se escriben completamente por encima de la línea de base, mientras que parte de estos caracteres se escriben debajo de la línea de base.

3 - ¿Por qué no verificar dónde está la línea de base de nuestra línea? He agregado algunos caracteres que muestran la línea de base de nuestra línea.

4 - ¿Por qué no agregar algunos caracteres en nuestros divs también para encontrar sus líneas de base en el div? Aquí, se agregaron algunos caracteres en divs para aclarar la línea base .

Ahora, cuando comprenda la línea de base, lea la siguiente versión simplificada sobre la línea de base de los bloques en línea.

i) Si el bloque en línea en cuestión tiene su propiedad de desbordamiento establecida en visible (que es por defecto, por lo que no es necesario configurarla). Entonces su línea de base sería la línea de base del bloque contenedor de la línea.

ii) Si el bloque en línea en cuestión tiene su propiedad de desbordamiento establecida en OTRO QUE visible. Entonces su margen inferior estaría en la línea de base de la línea del cuadro contenedor.

  • Primer punto en detalle

Ahora mire esto nuevamente para aclarar su concepto de lo que está sucediendo con el div verde . Si aún hay alguna confusión, aquí se agregan más caracteres cerca del div verde para establecer la línea base del bloque contenedor y la línea base div verde se alinea.

Bueno, ahora estoy afirmando que tienen la misma línea de base? ¿DERECHA?

5 - Entonces, ¿por qué no superponerlos y ver si encajan uno con el otro? Entonces, traigo el tercer div -left: 35px; para verificar si tienen la misma línea de base ahora ?

Ahora, tenemos nuestro primer punto probado.

  • Segundo punto en detalle

Bueno, después de la explicación del primer punto, el segundo punto es fácilmente digerible y ve que el primer div que tiene la propiedad de desbordamiento establecida en otra que no sea visible (oculta) tiene su margen inferior en la línea base de la línea.

Ahora, puede hacer un par de experimentos para ilustrarlo más.

  1. Establezca el primer desbordamiento div: visible (o elimínelo por completo) .
  2. Establezca el segundo desbordamiento div: que no sea visible .
  3. Establezca el desbordamiento de ambos divs: otro que no sea visible .

Ahora trae de vuelta tu desorden y mira si todo te parece bien.

  1. Recupere su div flotante (por supuesto, es necesario
    aumentar un poco el ancho del cuerpo) Verá que no tiene ningún efecto.
  2. Recupere los mismos márgenes impares .
  3. Establezca div verde en desbordamiento: visible a medida que establece su pregunta (esa desalineación se debe al aumento del ancho del borde de 1px a 5px, por lo que si ajusta el negativo a la izquierda , verá que no hay problema)
  4. Ahora elimine los caracteres adicionales que agregué para ayudar a comprender . (y, por supuesto, eliminar la izquierda negativa)
  5. Finalmente, reduzca el ancho del cuerpo porque ya no necesitamos uno más ancho.

Y ahora estamos de vuelta a donde comenzamos.

Espero haber respondido tu pregunta.

Gary Lindahl
fuente
1
Gracias por una gran explicación, pero no entendí su punto "Entonces, su línea de base sería la línea de base del bloque de contención de la línea". ¿Es lo mismo que la línea de base de la línea que dejó en claro en el segundo punto?
Shawn Taylor
2
Respuesta tardía. Solo noté el mismo problema, y ​​solo quería agradecer a Gary Lindahl por la buena explicación.
TimSPQR
+1 ntgCleaner Aunque aprecio las buenas respuestas, Gary Lindahl es mucho para leer y me faltan solo esas pocas líneas donde dice 'Solución: XY'
Codificador básico
Esta explicación detallada me pareció increíblemente informativa, gracias. Luché con un concepto por un tiempo, y he hecho un Fiddle actualizado que podría aclarar para otros.
jonsanders101
@ntgCleaner gracias hombre ... incluso después de toda la explicación no pude hacerlo funcionar. pero tu comentario lo hizo :)
supersan
330

El valor predeterminado para vertical-alignCSS es baseliney esta regla también se aplica con inline-blockleer esto http://www.brunildo.org/test/inline-block.html

Escribe vertical-align:topen tu inline-blockDIV.

Mira esto http://jsfiddle.net/WGCyu/1/

sandeep
fuente
3
¿Has leído mi pregunta? Nunca pedí corregir el problema.
Shawn Taylor
23
@ShawnTaylor: El título de la pregunta es muy engañoso. Leímos instintivamente el título y luego buscamos el código, si hay alguno. Raramente leemos el texto real. Es un mal hábito, pero probablemente deberías entender por qué sucede. : P
Purag
@sandeep: con respecto a su edición, entonces por qué firstDiv está alineado con la parte superior incluso cuando se elimina la alineación vertical
Shawn Taylor
@sandeep: el enlace que proporcionó es informativo, pero no ayuda en esta pregunta, ya que no describe el comportamiento display:inline-blockcombinado con float:left/right.
Zeta
2
@ThomasMcCabe Hardly; Si alguien publica una mala respuesta, merece ser rechazado para indicar a los futuros televidentes que hay algo malo, independientemente de sus buenas intenciones. Dicho esto, no creo que esta respuesta haya merecido un voto negativo; incluso en su forma original, proporcionó una pieza clave del rompecabezas omitida por la respuesta aceptada: que la alineación de la línea de base no es la única forma en que los elementos se alinean verticalmente, y que si cambia la vertical-alignpropiedad, ninguna de la complejidad descrita en el Se acepta la respuesta aceptada.
Mark Amery
9

Ver este ejemplo alternativo. La razón de tal comportamiento se describe en el módulo CSS3: línea: 3.2. Line Box wrapping [1] :

En general, el borde inicial de un cuadro de línea toca el borde inicial de su bloque contenedor y el borde final toca el borde final de su bloque contenedor. Sin embargo, los cuadros flotantes pueden interponerse entre el borde del bloque contenedor y el borde del cuadro de línea. Por lo tanto, aunque los cuadros de línea en el mismo contexto de formato en línea generalmente tienen el mismo avance de progresión en línea (el del bloque contenedor), pueden variar si el espacio disponible de progresión en línea se reduce debido a los flotadores [...]

Como puede ver, el tercer elemento se empuja hacia abajo, aunque no tiene una overflowpropiedad. La razón debe estar en otro lugar para encontrar. El segundo comportamiento que observa se describe en las Hojas de estilo en cascada Nivel 2 Revisión 1 (CSS 2.1) Especificación: 9.5 Flotadores [2] :

Dado que un flotador no está en el flujo, las cajas de bloques no posicionadas creadas antes y después de la caja del flotador fluyen verticalmente como si el flotador no existiera. Sin embargo, los cuadros de línea actuales y posteriores creados al lado del flotador se acortan según sea necesario para dejar espacio para el cuadro de margen del flotador.

Todos sus display:inline-block;divs utilizan un tipo especial de baselineen este caso 10.8 Cálculos de altura de línea: las propiedades 'line-height' y 'vertical-align' (final) [3] :

La línea base de un 'bloque en línea' es la línea base de su último cuadro de línea en el flujo normal, a menos que no tenga cuadros de línea en flujo o si su propiedad 'desbordamiento' tiene un valor calculado distinto de 'visible', en en cuyo caso la línea de base es el borde del margen inferior.

Por lo tanto, cuando utilice elementos y inline-blockelementos flotantes, el elemento flotante se empujará hacia un lado y el formato en línea se volverá a calcular de acuerdo con 1 . Por otro lado, los siguientes elementos se acortan si no encajan. Como ya está trabajando con una cantidad mínima de espacio, no hay otra forma de modificar sus elementos y luego presionarlos 2 . En este caso, el elemento más alto definirá el tamaño de su div de envoltura, definiendo así el baseline 3 , mientras que, por otro lado, la modificación de la posición y el ancho indicados en 2 no se puede aplicar a elementos de altura máxima espaciada mínima. En este caso resultará un comportamiento como en mi primera demostración.

Por último, la razón por la overflow:hiddenque evitará #firstDivque lo empujen al borde inferior de la suya #container, aunque no pude encontrar una razón en la sección 11 . Sin overflow:hiddenesto funciona como se exceptúa y define por 2 y 3 . Manifestación

TL; DR: Observe muy de cerca las recomendaciones de W3 y las implementaciones en el navegador. En mi humilde opinión, los elementos flotantes están determinados a mostrar un comportamiento inesperado si no conoce todos los cambios que hacen a los elementos que lo rodean. Aquí hay otra demostración que muestra un problema común con las carrozas.

Zeta
fuente
3
Este "estándar" es un desastre increíble. Es sorprendente que hayan podido hacer que estas cosas se comporten de manera coherente en todos los navegadores. Oh, espera, no, nunca han podido hacer eso.
Triynko
6

Originalmente comencé a responder esta pregunta , pero estaba bloqueado como engañado antes de que pudiera terminar, así que publico la respuesta aquí.

Primero, necesitamos entender qué inline-blockes.
La definición en MDN dice:

El elemento genera un cuadro de elemento de bloque que fluirá con el contenido circundante como si fuera un solo cuadro en línea (comportándose de manera muy similar a como lo haría un elemento reemplazado)

Para entender lo que está sucediendo aquí, tenemos que mirar vertical-align, y su valor predeterminado baseline.

visualizaciones de posición vertical
En esta ilustración, tiene esta tabla de colores:
Azul: la línea base
Rojo: la parte superior e inferior de la altura de la línea
Verde: La parte superior e inferior del cuadro de contenido en línea.

En el elemento #left, tiene contenido textual que controla cuál es la línea base. Esto significa que el texto dentro define la línea base para #left.
En el #derecho, no hay contenido, por lo que el navegador no tiene otra opción que usar la parte inferior del cuadro como línea de base.

Vea esta visualización donde dibujé la línea de base en un ejemplo donde el primer contenedor en línea tiene algo de texto, y el siguiente está vacío:

Línea base dibujada

Si alinea específicamente un elemento con la parte superior, realmente dice que alinea la parte superior de este elemento con la parte superior del cuadro de línea.

Esto podría ser más fácil de entender con un ejemplo.

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>

El resultado es este, y agregué la línea de base azul y el cuadro de línea roja: lo que sucede aquí es que la altura del cuadro de línea depende de cómo se distribuya el contenido de toda la línea. Esto significa que para calcular la alineación superior, las alineaciones de línea de base deben calcularse primero. El elemento tiene , por lo que esto no se utiliza para el posicionamiento de la línea base. pero el y se colocan verticalmente para que sus líneas de base estén alineadas. Cuando se hace esto, la altura del cuadro de línea ha aumentado, porque el elemento ha sido empujado un poco hacia arriba como resultado del tamaño de fuente más grande. Luego, se puede calcular la posición superior del elemento, y esto se encuentra en la parte superior del cuadro de línea.Explicación vertical alineada
#middlevertical-align:top#left#right#right#middle

temor
fuente
1

el problema es porque has aplicado flotante: izquierda en el segundo div. lo que hace que el segundo div venga del lado izquierdo y tu primer div caiga y venga después de tu segundo div. Si aplica float: a la izquierda en el primer div también, su problema desaparecerá.

desbordamiento: oculto no está causando ningún problema a su diseño, desbordamiento: oculto afecta solo a los elementos internos de un div, no tiene nada que ver con otros elementos que están fuera.

Pal Singh
fuente
Bueno, si se está presionando porque viene en segundo lugar después de div flotante, ¿por qué thirdDiv no baja?
Shawn Taylor
porque el tercer div tiene un segundo div antes que no tiene flotante: izquierda;
Pal Singh
Pero, ¿dónde se menciona esta regla que si algún div vendrá después del flotante div, entonces caerá hacia abajo? Revisé w3.org.
Shawn Taylor
el elemento que no está flotando cae a la línea de base y si ha hecho un voto negativo, debo decir que fue la respuesta más lógica
Pal Singh,
No, no voté negativo y sí, su respuesta no merece negativa. Acabo de votar hacia arriba.
Shawn Taylor
0

Intenta agregar padding:0;al cuerpo y eliminar el margen de tus divs.

Agregue background-color:*anycolor aparte del fondo * para verificar la diferencia.

LOLZ
fuente
Edite la respuesta para formatear el código. Puede formatear el código agregando el símbolo `antes de comenzar el código y después de terminar el código. como codepor ejemplo:. background-color:any color
JINO SHAJI
0

Intente hacer que todas las propiedades CSS de todos los elementos sean iguales.

Tuve un problema similar y, mientras solucionaba esto, identifiqué que estaba soltando un Elemento con la propiedad Fuente en Elemento Div.

Después de soltar ese Elemento con la propiedad Fuente, se alteró la alineación de todos los DIV. Para solucionar esto, configuré la propiedad Font para todos los elementos DIV de la misma manera que el elemento que se dejó caer.

En el siguiente ejemplo, el elemento Dropped de la clase ".dldCuboidButton" se define con font-size: 30 px.

Así que agregué la misma propiedad a las clases restantes, es decir .cuboidRecycle, .liCollect, .dldCollect que utilizan los elementos DIV. De esa manera, todos los elementos DIV siguen las mismas medidas antes y después de colocar el elemento en él.

.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;
  }

Aquí está el ejemplo de HTML creado dinámicamente usando el CSS anterior.

$("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
fuente