Perché le percentuali di margine / riempimento nei CSS sono sempre calcolate in base alla larghezza?


130

Se osservi le specifiche del modello di box CSS , osserverai quanto segue:

La percentuale [margine] viene calcolata rispetto alla larghezza del blocco contenitore della casella generata. Si noti che ciò vale anche per 'margin-top' e 'margin-bottom'. Se la larghezza del blocco contenitore dipende da questo elemento, il layout risultante non è definito in CSS 2.1. (enfatizzare il mio)

Questo è davvero vero. Ma perchè ? Cosa mai costringerebbe nessuno a progettarlo in questo modo? È facile pensare a scenari in cui si desidera, ad esempio una certa cosa deve essere sempre inferiore del 25% dalla parte superiore della pagina, ma è difficile trovare un motivo per cui si desidera che l'imbottitura verticale sia relativa alla dimensione orizzontale di il genitore.

Ecco un esempio del fenomeno a cui mi riferisco:

<div style="border: 1px solid red; margin: 0; padding: 0; width: 200px; height: 800px;">
  This div is 200x800.
  <div style="border: 1px solid blue; margin: 10% 0 0 10%;">
    This div has top-margin of 10% and left-margin of 10% with respect to its parent.
  </div>
</div>

http://jsfiddle.net/8JDYD/


3
Il mio pensiero iniziale è che provocherebbe ambiguità su cosa margin: 25%significhi effettivamente. Non sarebbe un margine pari, anche se il codice suggerisce che lo sia. Non ho prove a sostegno di questo, ma sembra ragionevole.
Ryan Kinal,

4
jsFiddle dei miei pensieri . L'altezza è molto più variabile rispetto alla larghezza, quindi farebbe spostare i margini in modi difficili da prevedere ogni volta che il contenuto cambiava.
RichardTowers,

1
@Ryan: È vero, non sarebbe un margine pari, ma poi di nuovo, se dici height: 10%; width: 10%che non otterrai nemmeno un elemento quadrato.
mqp

4
Secondo dev.w3.org/csswg/css3-box/#the-margin-properties afferma Note that in a horizontal flow, percentages on ‘margin-top’ and ‘margin-bottom’ are relative to the width of the containing block, not the height (and in vertical flow, ‘margin-left’ and ‘margin-right’ are relative to the height, not the width).Quindi va in entrambe le direzioni
Adam Sweeney

1
@Ryan Penso che abbiamo un vincitore. Cerca qui una demo - jsFiddle
RichardTowers,

Risposte:


60

Trasferire il mio commento a una risposta, perché ha un senso logico. Tuttavia, tieni presente che si tratta di congetture infondate. Il vero ragionamento sul perché le specifiche siano scritte in questo modo è ancora, tecnicamente, sconosciuto.

L'altezza dell'elemento è definita dall'altezza dei bambini. Se un elemento ha padding-top: 10% (rispetto all'altezza del genitore), ciò influenzerà l'altezza del genitore. Poiché l'altezza del bambino dipende dall'altezza del genitore e l'altezza del genitore dipende dall'altezza del bambino, avremo un'altezza imprecisa o un ciclo infinito. Certo, questo riguarda solo il caso in cui offset parent === parent, ma comunque. È un caso strano che è difficile da risolvere.

Aggiornamento: le ultime due frasi potrebbero non essere del tutto esatte. L'altezza dell'elemento foglia (bambino senza figli) ha un effetto sull'altezza di tutti gli elementi sopra di esso, quindi influisce su molte situazioni diverse.


1
Si noti che ci sono eccezioni a questa regola: la sezione 10.6 di CSS2.1 copre quasi tutte le istanze di calcolo delle altezze per vari tipi di scatole. E in effetti, i casi che comportano una codipendenza tra genitore e figlio in altezza tendono a condurre a comportamenti indefiniti.
BoltClock

1
@sanjaypoyzer Immagino, nel caso più semplice, che i browser calcolino le larghezze dei blocchi dall'esterno in (radice ai suggerimenti), quindi scorrano il contenuto in quei blocchi per determinare le loro altezze (punte al root).
sam,

9
Perché il W3C lo fa costantemente? Apparentemente "semantico" al W3C è l'equivalente di dover provvedere a persone che non possono pensare logicamente, il che non ha senso. È come lamentarsi di quanto siano confuse e stupide le persone nel mondo, diffondendo più confusione e stupidità. Il ragionamento che hai fornito non ha senso: lo stesso argomento si applica alle larghezze, ma funziona perfettamente. Tutto ciò che sarebbe necessario è impostare un contesto e una direzione in cui determinare le altezze, a meno che l'altezza del genitore non sia impostata in pixel o qualcosa di immutabile, quindi non c'è molto problema.
u353,

3
Tale dipendenza è una formula algebrica che ha una soluzione e non si tradurrà in un ciclo infinito a meno che tu non scelga di risolverlo in un modo che non rispetti questo. Di 'l'altezza del genitore h_p. Un'imbottitura superiore del 10% renderà l'altezza del bambino h_c = h_ci + 0.1h_p, dove si h_citrova l'altezza interna del bambino e non dipende dall'altezza del genitore. Per un bambino trovi semplicemente l'altezza del genitore dall'equazione h_p = h_ci + 0.1h_p=> h_p = h_ci / 0.9. Puoi sempre farlo, non importa quanti figli hai, anche per imbottiture diverse. È solo una sconosciuta ( h_p) e un'equazione.
jeteon,

2
Non penso che il calcolo infinito sia la ragione. Un semplice motivo è che: l'utilizzo di widthrisultati comporta lo stesso problema in orizzontale.
Gioia,

30

Perché il margine "n%" (e il riempimento) siano gli stessi per margine-alto / margine-destro / margine-basso / margine-sinistro, tutti e quattro devono essere relativi alla stessa base. Se top / bottom usasse una base diversa da sinistra / destra ', allora il margine "n%" (e il riempimento) non significherebbe la stessa cosa su tutti e quattro i lati.

(Si noti inoltre che il margine superiore / inferiore rispetto alla larghezza consente uno strano hack CSS che consente di specificare una casella con proporzioni invariate ... anche se la casella viene riscalata.)


... una risposta sorprendentemente semplice. Sebbene tutte le congetture di cui sopra abbiano dei meriti, questo è un buon punto. Sembra forse un caso in cui più soluzioni sarebbero corrette, quindi hanno semplicemente scelto la più probabile da usare ... forse?
Dudewad,

1
Suppongo che sarebbe bello avere un elemento aggiuntivo nella sintassi in modo da poter scrivere dire padding: n [type]. Quindi avresti padding: 5% logical(ciò che l'OP suggerisce) al contrario padding: 5% widthdel secondo parametro impostato su "larghezza" per compatibilità con le versioni precedenti.
jeteon,

5
"n% di margine (e riempimento) non significherebbe la stessa cosa su tutti e quattro i lati" - Ma perché sarebbe un problema?
Herbertusz,

4

Voto per la risposta di @ChuckKollars dopo aver giocato con questo JSFiddle (su Chrome 46.0.2490.86) e facendo riferimento a questo post (scritto in cinese).


Uno dei motivi principali per cui si contrappone la congettura del calcolo infinito è che: usare le widthfacce è lo stesso problema di calcolo infinito .

Dai un'occhiata a questo JSFiddle , il parentdisplay è inline-block, che è idoneo a definire il margine / padding su di esso. Il childha valore margine 20%. Se seguiamo la congettura del calcolo infinito :

  1. La larghezza della childdipende dalparent
  2. La larghezza della parentdipende dalchild

Di conseguenza, Chrome interrompe il calcolo da qualche parte, risultando:

inserisci qui la descrizione dell'immagine

Se provi ad espandere il pannello "risultato" in orizzontale sul JSFiddle, scoprirai che la loro larghezza non cambierà. Si noti che il contenuto in childè racchiuso in due righe (non, diciamo, una riga), perché? Immagino che Chrome lo abbia semplicemente programmato da qualche parte. Se modifichi il childcontenuto per renderlo più ( JSFiddle ), scoprirai che finché c'è spazio extra in orizzontale, Chrome mantiene il contenuto due righe.

Quindi possiamo vedere: esiste un modo per impedire il calcolo infinito .


Sono d'accordo con la congettura che: questo disegno serve solo a mantenere i quattro valori di margine / riempimento sulla stessa misura.

questo post (scritto in cinese) propone anche un'altra ragione: è a causa dell'orientamento della lettura / composizione. Leggiamo dall'alto verso il basso, con la larghezza fissa e l'altezza infinita (praticamente).


Questo perché le pagine Web scorrono verticalmente in una direzione generalmente infinita; quindi la larghezza può essere calcolata dalla larghezza della finestra del browser. L'unico modo in cui gli elementi sono più larghi dello schermo è se specifichi che la loro larghezza è maggiore. Gli elementi di blocco tipici sono la larghezza del 100% e si espandono automaticamente nella direzione verticale (sconosciuto). Ecco perché la larghezza non ha lo stesso problema.
Lucent Fox,

3

Mi rendo conto che l'OP si sta chiedendo perché la specifica CSS definisce le percentuali di margine superiore / inferiore come% della larghezza (e non, come si suppone, altezza), ma ho pensato che potesse anche essere utile pubblicare una potenziale soluzione.

La maggior parte dei browser moderni supporta vw e vh ora che consente di specificare i numeri di margine rispetto alla larghezza della vista e all'altezza della vista.

100vw / 100vh equivalgono a 100% larghezza / 100% altezza (rispettivamente) se non c'è barra di scorrimento; se è presente una barra di scorrimento, i numeri del riquadro di visualizzazione non tengono conto di questo (mentre i numeri% lo fanno). Per fortuna, quasi tutti i browser utilizzano dimensioni della barra di scorrimento di 17 px ( vedi qui ), quindi puoi utilizzare la funzione css calc per tenerne conto. Se non sai se verrà visualizzata o meno una barra di scorrimento, questa soluzione non funzionerà.

Ad esempio: Supponendo che nessuna barra di scorrimento orizzontale, un margine superiore del 50% dell'altezza, possa essere definito come "margine superiore: 50vh;". Con una barra di scorrimento orizzontale, questo potrebbe essere definito come "margin-top: calc (0,5 * (100vh - 17px));" (ricorda che gli operatori meno e più in calc richiedono spazi su entrambi i lati!).


1
È una soluzione utile in molti casi, ma ci sono molti esempi in cui non funziona (ad esempio se stai cercando di adattare il contenuto in modo proporzionale alla dimensione di un contenitore flexbox che cresce per riempire lo spazio disponibile mentre c'è un'altra scatola con contenuto variabile).
Jules,
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.