Perché questo elemento di blocco in linea viene spinto verso il basso?


238

Di seguito è riportato il mio codice e voglio capire perché #firstDiv viene spinto verso il basso da tutti i browser. Voglio davvero capire il funzionamento interiore del fatto che è stato spinto verso il basso anziché tirarlo verso l'alto in un modo o nell'altro. (e so come allineare le loro cime :))

E so che è troppo pieno: nascosto ciò che lo sta causando, ma non sono sicuro del perché lo spinga verso il basso.

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/ .

Risposte:


361

Fondamentalmente hai aggiunto più disordine nel tuo codice che sta creando più confusione, quindi prima provo a rimuovere il disordine che ostacola la comprensione del vero problema.

Prima di tutto dobbiamo stabilire che qual è la vera domanda? È per questo che " inline-block" l'elemento viene spinto verso il basso.

Ora iniziamo a capirlo e rimuovere prima il disordine.

1 - Perché non dare a tutte e tre le div la stessa larghezza del bordo? Diamo.

2 - L'elemento mobile ha qualche connessione con l'elemento di blocco inline che viene spinto verso il basso? No, non c'entra niente.

Quindi, abbiamo rimosso del tutto quel div . E stai assistendo allo stesso comportamento dell'elemento di blocco inline che viene spinto verso il basso.

Arriva il turno di alcune pubblicazioni per cogliere l'idea delle caselle di riga e di come sono allineate nella stessa riga esp leggere attentamente l'ultimo paragrafo perché sta la risposta alla tua domanda.

La linea di base di un 'blocco inline' è la linea di base della sua ultima casella di linea nel flusso normale, a meno che non abbia né caselle di linea in-flow o se la sua proprietà 'overflow' abbia un valore calcolato diverso da 'visibile', in in tal caso la linea di base è il margine inferiore.

Se non sei sicuro della linea di base, ecco una breve spiegazione in parole semplici.

Tutti i caratteri tranne 'gjpqy' sono scritti sulla linea di base che puoi pensare alla linea di base come se disegnassi una linea orizzontale semplice come quella sottolineata proprio sotto questi "caratteri casuali", allora sarà la linea di base ma ora se scrivi una qualsiasi di "gjpqy" i personaggi sulla stessa linea, quindi la parte inferiore di questi caratteri cadrebbe sotto la linea.

Quindi, possiamo dire che tutti i caratteri tranne 'gjpqy' sono scritti completamente sopra la linea di base mentre alcune parti di questi caratteri sono scritte sotto la linea di base.

3 - Perché non controllare dove si trova la linea di base della nostra linea? Ho aggiunto alcuni caratteri che mostrano la linea di base della nostra linea.

4 - Perché non aggiungere anche alcuni personaggi nei nostri div per trovare le loro basi nel div? Qui, alcuni personaggi aggiunti in div per chiarire la linea di base .

Ora, quando capisci la baseline, leggi la seguente versione semplificata sulla baseline dei blocchi inline.

i) Se il blocco inline in questione ha la proprietà di overflow impostata su visibile (impostazione predefinita, quindi non è necessario impostarla). Quindi la sua linea di base sarebbe la linea di base del blocco contenitore della linea.

ii) Se il blocco inline in questione ha la proprietà di overflow impostata su ALTRO DI QUELLO visibile. Quindi il suo margine inferiore sarebbe sulla linea di base della riga della casella di contenimento.

  • Primo punto in dettaglio

Ora guarda di nuovo questo per chiarire il tuo concetto che cosa sta succedendo con div verde . Se ancora qualche confusione, qui vengono aggiunti più caratteri vicino al div verde per stabilire la linea di base del blocco contenitore e la linea di base del div verde è allineata.

Bene, ora sto sostenendo che hanno la stessa base? GIUSTO?

5 - Allora perché non sovrapporli e vedere se sono adatti l'uno sull'altro? Quindi, porto il terzo div-a sinistra: 35px; controllare se hanno la stessa linea di base ora ?

Ora, abbiamo dimostrato il nostro primo punto.

  • Secondo punto in dettaglio

Bene, dopo la spiegazione del primo punto, il secondo punto è facilmente digeribile e vedi che il primo div che ha la proprietà di overflow impostata su diverso da visibile (nascosto) ha il suo margine inferiore sulla linea di base della linea.

Ora puoi fare un paio di esperimenti per illustrarlo ulteriormente.

  1. Imposta il primo overflow del div: visibile (o rimuovilo del tutto) .
  2. Imposta il secondo overflow del div: diverso da quello visibile .
  3. Imposta l' overflow di entrambi i div: diverso da quello visibile .

Ora riporta il tuo disordine e vedi se tutto ti sta bene.

  1. Riporta il tuo div fluttuante (ovviamente c'è bisogno di
    aumentare un po 'di larghezza del corpo) Vedi che non ha alcun effetto.
  2. Riporta gli stessi margini dispari .
  3. Imposta div verde su overflow: visibile mentre imposti la tua domanda (quel disallineamento è dovuto all'aumento della larghezza del bordo da 1px a 5px, quindi se regola il negativo a sinistra vedrai che non c'è problema)
  4. Ora rimuovi i caratteri aggiuntivi che ho aggiunto per aiutare a capire . (e ovviamente rimuovi la sinistra negativa)
  5. Riduci infine la larghezza del corpo perché non ne abbiamo più bisogno.

E ora siamo tornati da dove siamo partiti.

Spero di aver risposto alla tua domanda.


1
Grazie per un'ottima spiegazione ma non ho capito il tuo punto "Quindi la sua linea di base sarebbe la linea di base del blocco contenitore della linea." È lo stesso della linea di base della linea come chiarito nel secondo punto?
Shawn Taylor,

2
Risposta tardiva. Ho appena notato lo stesso problema e volevo solo ringraziare Gary Lindahl per la spiegazione NICE.
TimSPQR,

+1 ntgCleaner Anche se apprezzo le buone risposte, Gary Lindahl è così tanto da leggere e mi mancano solo quelle poche righe in cui si dice 'Soluzione: XY'
Basic Coder

Ho trovato questa spiegazione dettagliata incredibilmente istruttiva, grazie. Ho lottato con un concetto per un po 'e ho creato un violino aggiornato che potrebbe chiarire per gli altri.
jonsanders101,

@ntgCleaner grazie amico .. anche dopo tutte le spiegazioni non sono riuscito a farlo funzionare. ma il tuo commento è stato fatto :)
supersan

330

Il valore predefinito per vertical-alignin CSS è baselinee questa regola si applica anche con inline-blockleggi questo http://www.brunildo.org/test/inline-block.html

Scrivi vertical-align:topnel tuo inline-blockDIV.

Controlla questo http://jsfiddle.net/WGCyu/1/


3
Hai letto la mia domanda? Non ho mai chiesto di correggere il problema.
Shawn Taylor,

23
@ShawnTaylor: il titolo della domanda è molto fuorviante. Istintivamente leggiamo il titolo, quindi spariamo per il codice, se presente. Raramente leggiamo il testo reale. È una cattiva abitudine ma probabilmente dovresti capire perché succede. : P
Purag,

@sandeep: per quanto riguarda la tua modifica, allora perché firstDiv è allineato in alto anche quando l'allineamento verticale viene rimosso da esso
Shawn Taylor

@sandeep: il link che hai fornito è informativo, ma non aiuta su questa domanda poiché non descrive il comportamento di display:inline-blockcombinato con float:left/right.
Zeta,

2
@ThomasMcCabe Hardly; se qualcuno pubblica una risposta negativa, merita di essere sottoposto a downgrade per segnalare ai futuri spettatori che c'è qualcosa che non va, indipendentemente dalle loro buone intenzioni. Detto questo, non credo che questa risposta abbia mai meritato un voto negativo; anche nella sua forma originale, ha fornito un pezzo chiave del puzzle omesso dalla risposta accettata: l'allineamento della linea di base non è l'unico modo in cui gli elementi vengono allineati verticalmente e che se si modifica la vertical-alignproprietà, nessuna della complessità descritta nella si applica la risposta accettata.
Mark Amery,


9

Visualizza questo esempio alternativo. La ragione di tale comportamento è descritta nel modulo CSS3: linea: 3.2. Confezione Line Box [1] :

In generale, il bordo iniziale di una casella di linea tocca il bordo iniziale del suo blocco contenitore e il bordo finale tocca il bordo finale del suo blocco contenitore. Tuttavia, i riquadri mobili possono trovarsi tra il bordo del blocco contenitore e il bordo del riquadro di linea. Pertanto, sebbene le caselle di linea nello stesso contesto di formattazione in linea abbiano generalmente lo stesso avanzamento di progressione in linea (quello del blocco contenitore), possono variare se lo spazio di progressione in linea disponibile viene ridotto a causa dei float [...]

Come puoi vedere, il terzo elemento viene spinto verso il basso, sebbene non abbia una overflowproprietà. Il motivo deve essere altrove da trovare. Il secondo comportamento che si nota è descritto nella specifica Cascading Style Sheets Level 2 Revision 1 (CSS 2.1): 9.5 Floats [2] :

Poiché un galleggiante non è nel flusso, le scatole di blocchi non posizionate create prima e dopo la scatola del galleggiante scorrono verticalmente come se il galleggiante non esistesse. Tuttavia, le caselle di riga correnti e successive create accanto al float vengono accorciate se necessario per fare spazio alla casella del margine del float.

Tutti i tuoi display:inline-block;div utilizzano baselinein questo caso un tipo speciale di 10.8 Calcoli dell'altezza della linea: le proprietà 'line-height' e 'vertical-align' (very end) [3] :

La linea di base di un 'blocco inline' è la linea di base della sua ultima casella di linea nel flusso normale, a meno che non abbia né caselle di linea in-flow o se la sua proprietà 'overflow' abbia un valore calcolato diverso da 'visibile', in in tal caso la linea di base è il margine inferiore.

Pertanto, quando si utilizzano elementi e inline-blockelementi mobili, l'elemento mobile verrà spinto lateralmente e la formattazione in linea verrà ricalcolata in base a 1 . D'altra parte, gli elementi successivi vengono abbreviati se non si adattano. Dato che stai già lavorando con una quantità minima di spazio, non c'è altro modo per modificare i tuoi elementi e poi spingerli 2 . In questo caso, l'elemento più alto definirà la dimensione del div avvolgimento, definendo così il baseline 3 , mentre d'altra parte la modifica della posizione e della larghezza dichiarata in 2 non può essere applicata a tali elementi di altezza massima con spaziatura minima. In questo caso si verificherà un comportamento come nella mia primissima demo.

Infine, il motivo overflow:hiddenper cui impedirai #firstDivdi essere spinto al limite inferiore del tuo #container, anche se non ho trovato un motivo nella sezione 11 . Senza overflow:hiddenfunziona come escluso e definito da 2 e 3 . dimostrazione

TL; DR: dai un'occhiata molto da vicino alle raccomandazioni W3 e alle implementazioni nel browser. Secondo la mia modesta opinione, gli elementi fluttuanti sono determinati a mostrare comportamenti inaspettati se non si conoscono tutti i cambiamenti che apportano agli elementi circostanti. Ecco un'altra demo che mostra un problema comune con i float.


3
Questo "standard" è un casino incredibile. È incredibile che siano stati in grado di far sì che queste cose si comportino in modo coerente tra i browser. Oh aspetta, no, non sono mai stati in grado di farlo.
Triynko,

6

Inizialmente ho iniziato a rispondere a questa domanda , ma era bloccato come duplicato prima che potessi finire, quindi inserisco la risposta qui.

Innanzitutto, dobbiamo capire cos'è inline-block.
La definizione in MDN dice:

L'elemento genera una casella di elemento a blocchi che verrà trasmessa con il contenuto circostante come se fosse una singola casella incorporata (comportandosi in modo molto simile a un elemento sostituito)

Per capire cosa sta succedendo qui, dobbiamo guardare vertical-align, ed è il valore predefinito baseline.

visualizzazioni di posizione verticale
In questa illustrazione hai questa tabella di colori:
Blu: la linea di base
Rosso: la parte superiore e inferiore dell'altezza della linea
Verde: la parte superiore e inferiore della casella del contenuto incorporato.

Nell'elemento #left, hai del contenuto testuale che controlla qual è la linea di base. Ciò significa che il testo all'interno definisce la linea di base per #left.
In #right, non ci sono contenuti, quindi il browser non ha altra opzione che usare la casella in basso come linea di base.

Vedi questa visualizzazione in cui ho tracciato la linea di base su un esempio in cui il primo contenitore in linea ha del testo e il successivo è vuoto:

Linea di base disegnata

Se si allinea in modo specifico un elemento in alto, si dice in realtà che si allinea la parte superiore di questo elemento alla parte superiore della casella della riga.

Questo potrebbe essere più facile da capire da un esempio.

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>

Il risultato è questo - e ho aggiunto la linea di base blu e la casella di linea rossa: quello che succede qui è che l'altezza della casella di linea dipende da come è strutturato il contenuto dell'intera linea. Ciò significa che per calcolare l'allineamento superiore, gli allineamenti della linea di base devono essere calcolati per primi. L' elemento ha , quindi questo non è usato per il posizionamento di base. ma i e sono posizionati verticalmente in modo che le loro linee di base siano allineate. Al termine, l'altezza della casella di linea è aumentata, poiché l' elemento è stato leggermente sollevato a causa della dimensione del carattere maggiore. Quindi è possibile calcolare la posizione superiore per l' elemento, che si trova nella parte superiore della casella della riga.Spiegato vertical-align
#middlevertical-align:top#left#right#right#middle


1

il problema è perché hai applicato float: lasciato sul secondo div. che fa in modo che il secondo div arrivi sul lato sinistro e il tuo primo div scenda e arrivi dopo il secondo div. Se applichi float: lasciato anche sul primo div, il tuo problema sparirà.

overflow: nascosto non causa problemi al layout, overflow: nascosto influisce solo sugli elementi interni di un div, non ha nulla a che fare con altri elementi esterni.


Bene, se viene spinto perché arriva secondo dopo div fluttuato, allora perché thirdDiv non scende?
Shawn Taylor,

perché il terzo div ha un secondo div prima che non ha float: left;
Pal Singh,

Ma dove viene menzionata questa regola che se qualche div verrà dopo un div fluttuato, scenderà verso il basso? Ho controllato w3.org.
Shawn Taylor,

l'elemento che non fluttua scende alla linea di base e se avessi fatto un voto negativo di quello che devo dire che era la risposta più logica
Pal Singh,

No, non ho votato negativamente e sì, la tua risposta non merita un giudizio negativo. Ho appena votato verso l'alto.
Shawn Taylor,

0

Prova ad aggiungere padding:0;al corpo e rimuovere il margine dei tuoi div.

Aggiungi background-color:*anycolore oltre allo sfondo * per verificare la differenza.


Modifica la risposta per formattare il codice, puoi formattare il codice aggiungendo il simbolo `prima di iniziare il codice e dopo aver terminato il codice. come codead esempio:. background-color:any color
JINO SHAJI,

0

Prova a rendere tutte le proprietà CSS di tutti gli elementi uguali.

Ho avuto un problema simile e mentre risolvo questo ho identificato che stavo lasciando cadere un elemento con proprietà Font in Div Element.

Dopo aver lasciato cadere l'elemento con la proprietà Font, l'allineamento di tutti i DIV è stato disturbato. Per risolvere questo problema, ho impostato la proprietà Font su tutti gli elementi DIV allo stesso modo dell'elemento che viene rilasciato in esso.

Nel seguente esempio, l'elemento Dropped della classe ".dldCuboidButton" definito con dimensione carattere: 30 px.

Quindi ho aggiunto la stessa proprietà alle classi rimanenti, ad esempio .cuboidRecycle, .liCollect, .dldCollect che sono utilizzati dagli elementi DIV. In questo modo tutti gli elementi DIV seguono le stesse misurazioni prima e dopo aver lasciato cadere l'elemento al suo interno.

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

Ecco l'esempio di HTML creato dinamicamente utilizzando CSS sopra.

$("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>" 
);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.