Dimensionamento box CSS3: margin-box; Perchè no?


139

Perché non l'abbiamo box-sizing: margin-box;? Di solito quando inseriamo i box-sizing: border-box;nostri fogli di stile intendiamo davvero il primo.


Esempio:

Diciamo che ho un layout di pagina a 2 colonne. Entrambe le colonne hanno una larghezza del 50%, ma sembrano un po 'brutte perché non c'è grondaia (spazio nel mezzo); Di seguito è riportato il CSS:

.col2 {
    width: 50%;
    float: left;
}


Per applicare una grondaia potresti pensare che potremmo semplicemente impostare un margine destro sulla prima delle 2 colonne; qualcosa come questo:

.col2:first-child {
    margin-right: 24px;
}

Ma ciò farebbe avvolgere la seconda colonna in una nuova riga, poiché è vero quanto segue:

50% + 50% + 24px > 100%

box-sizing: margin-box;risolverebbe questo problema includendo il margine nella larghezza calcolata dell'elemento. Lo troverei molto utile se non più utile di box-sizing: border-box;.


30
"Perché non l'abbiamo box-sizing: margin-box;?" Perché mentre i margini orizzontali non collassano, una simile proposta interferirebbe seriamente con il collasso dei margini verticali. Comunque, se vuoi proporre qualcosa per la standardizzazione, StackTranslate.it non è il posto giusto. Prova le mailing list.
BoltClock

16
In alcune situazioni, puoi aggirare il problema utilizzando border: xxx solid transparent;, poiché il bordo è incluso in border-box. Ciò interromperà alcune altre cose, come ad esempio box-shadow.
Nathan Osman,

28
Stiamo chiudendo tutte le domande sugli standard come "non costruttive" ora ?? È una domanda giusta da porre, e ha anche una risposta semplice: non abbiamo box-sizing: margin-boxperché non funzionerebbe con il collasso dei margini.
thomasrutter,

@thomasrutter: non c'era una ragione migliore per dirlo al momento in cui l'ho chiuso, che era più di un anno fa. Ad ogni modo, "non costruttivo" è sparito ora (che significa no, in realtà non chiudiamo più nulla come non costruttivo), e poiché l'intero "Ho un'idea, ecco come funziona, facciamo di questo uno standard!" la cosa è stata rimossa da quando è stata chiusa l'ultima volta ora suona davvero come un pratico "perché X non può funzionare?" domanda. È ancora una domanda incredibilmente speculativa (il mio ragionamento sopra non è altro che un'ipotesi istruita), ma non commenterò ulteriormente.
BoltClock

perché non avere semplicemente un wrapping / div se vuoi spaziare: codepen.io/chriscoyier/pen/eGcLw
ashley,

Risposte:


55

Non potresti usare width: calc(50% - 24px);per i tuoi compagni? Quindi impostare i margini.


5
Dipende fortemente dal browser. Probabilmente intorno al 2020, ie15 lo supporterà e ti sarà permesso di usarlo anche nel tuo lavoro :-(
peterh - Ripristina Monica

1
Non sembra funzionare così bene in Firefox? (o qualcos'altro che ho fatto non lo è)
Laurengineer,

@ Morgan Feeney: Sì, ma il dimensionamento delle scatole non ha un valore chiamato margin-box (che è il punto centrale di questa domanda). Anche se un tale valore è stato introdotto ora, come proponete di rattoppare / polifilare / ridimensionarlo nei browser esistenti?
BoltClock

Sì, ma ... rispondendo specificamente a una risposta che suggerisce calc () come soluzione alternativa.
Morgan Feeney,

Non sono sicuro che ciò si applichi all'esempio specifico, ma un grave aspetto negativo nell'uso di calc () nel nostro scenario (come in FF 53.0.3) è che il suo comportamento non è analogo a quello della larghezza: X%; Da ciò che possiamo vedere "calc" viene eseguito al momento del rendering iniziale a un Xpx statico. Ciò significa che, diversamente dalla larghezza: X%, la colonna calcolata non si ridimensiona automaticamente con il ridimensionamento del contenitore.
Pancho,

16

Penso che potremmo avere un box-sizing: margin-box. Il modello di casella CSS mostra esattamente quali sono le posizioni dei margini dei frame.

Esistono problemi minori, ad esempio le caselle dei margini possono sovrapporsi, ma non sono difficili da risolvere.

Penso che la situazione sia la stessa, come possiamo vedere con le combinazioni overflow-x& overflow-y, con i div assoluti positionied nelle celle della tabella, con la combinazione di min | max-width | height con il ridimensionamento della casella, e così via.

Ci sono funzionalità, funzionalità davvero semplici, che gli sviluppatori del browser semplicemente non sviluppano.

IMHO, box-sizing: margin-boxerano una funzionalità molto utile. Un'altra caratteristica utile era la box-sizing: padding-box, esiste almeno nello standard, ma non è stata implementata in nessuno dei principali browser. Neanche nel nuovissimo chrome!


Nota: il commento di @Oriol: Firefox ha implementato il dimensionamento del box: padding-box. Ma altri no, ed è stato rimosso dalle specifiche. Firefox lo rimuoverà nella versione 50. Triste.


2
Firefox ha implementato box-sizing: padding-box. Ma altri no, ed è stato rimosso dalle specifiche. Firefox lo rimuoverà nella versione 50. Triste.
Oriol,

6

Il ragazzo in alto sta chiedendo di aggiungere margine alla larghezza complessiva, inclusi imbottitura e bordo. Il fatto è che il margine viene applicato fuori dagli schemi e l'imbottitura e il bordo non lo sono, durante l'utilizzo border-box.

Ho cercato di realizzare l' border-marginidea. Quello che ho scoperto è che se si utilizza il margine è possibile aggiungere una classe .lastall'ultimo elemento (con margine, quindi applicare un margine pari a zero o utilizzare :last-child/:last-of-type). Oppure aggiungi tutti i margini uguali (in modo simile alla versione di imbottitura sopra).

Vedi esempi qui: http://codepen.io/mofeenster/pen/Anidc

border-boxcalcola la larghezza dell'elemento + la sua imbottitura + il suo bordo come larghezza totale. Quindi se hai 2 divsecondi di larghezza del 50%, saranno adiacenti. Se aggiungi 8pxloro delle imbottiture, avrai una grondaia di 16px. Combinalo con un elemento avvolgente - che ha anche un'imbottitura 8px- avrai una griglia ben disposta con uguali grondaie tutto intorno.

Vedi questo esempio qui: http://codepen.io/mofeenster/pen/vGgje

Quest'ultimo è il mio metodo preferito.


4

Sono sicuro che tutto ciò è ovvio, ma lo scrivo comunque perché ... beh, ho bisogno dell'esercizio. Il seguente risultato non sarebbe altrettanto efficace di box-sizing: margin-box;:

.col2 {
    width: 45%;
    height: 90%;
    margin: 5% 2.5%;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    float: left;
}

http://jsfiddle.net/Fg3hg/

box-sizingviene utilizzato per controllare da quale punto l'imbottitura e il bordo vengono valutati in base alla dimensione complessiva dell'elemento. Quindi, sebbene non sia kosher includere pxmargini con una %larghezza (come sempre accade), è più semplice calcolare quale dovrebbe essere la percentuale relativa perché non è necessario incorporare imbottitura e bordi alla larghezza definita.


9
Il caso d'uso di qualcosa come margin-box è abilitare la miscelazione di larghezze percentuali con margini di pixel. Se vuoi due scatole del 50% con un margine di 1px tra loro, questo non può essere realizzato con un margine percentuale dell'1% di simili - alcune dimensioni di schermi di piccole dimensioni arrotondano dell'1% fino a 0 pixel e improvvisamente non hai alcun margine. Ciò di cui abbiamo davvero bisogno è un maggiore supporto del browser per calc () come mostra @Slouch, o il modello flexbox.

1
Se questa è la cura, il contenitore genitore sarebbe inferiore a 100px e spero che alcuni elementi di design vengano ripensati a quel punto. Ci sono alcune altre cose che potresti fare con elementi nidificati e simili, ma, sì, avere calcoli variabili sarebbe piuttosto stupefacente. Se ti piacciono cose come sass o meno, penso che facciano un sacco di queste cose. Ho giocato con loro, ma non sono ancora un Jedi.
Plummer,

2
Quello che stai suggerendo è una soluzione. Non è un modo ideale per scrivere CSS quando lavori con layout complessi. Stai assumendo che il progettista o l'autore voglia utilizzare le percentuali nel loro design. Inoltre, indipendentemente da questo problema, anche se si utilizza la funzione calc () per calcolare la spaziatura utilizzando i margini dei pixel, si limita comunque il progettista perché devono predeterminare quale sia il margine di scorrimento, anziché consentire che venga sovrascritto mediante CSS.
limitlessloop,

Non capisco il tuo punto. Il problema attuale era che l'inclusione di px e% causa interruzioni di riga perché il margine non è incluso nel calcolo delle dimensioni. Un margine non è incluso nella dimensione di un elemento, è lo spazio che vuoi apparire attorno a un elemento. Inoltre, come margin-boxgestire i calcoli del margine multidimensionale? @mediapunti di interruzione max-widthe min-widthfunzionano bene. Immagino che margin-boxpotrebbe ridurre un po 'di gonfiore, ma ho anche ragioni per cui può essere considerato ridondante.
Plummer,

Perché nessuno menziona che questo margine percentuale è la percentuale di larghezza per qualche motivo ... non importa altezza o larghezza. Viene utilizzata la larghezza del genitore. Il che è bizzare a dir poco .. quindi il codice sopra non dovrebbe funzionare e non funziona. a meno che non si equivalgano altezza e larghezza.
Muhammad Umer,

4

Questo perché l'attributo di ridimensionamento della casella si riferisce alla dimensione di un elemento dopo aver calcolato i valori specifici della dimensione specificati (riempimento, bordi). "box-sizing: border-box" imposta l'altezza / larghezza di un elemento e prende in considerazione l'imbottitura e la larghezza del bordo. L'ambito del margine di un elemento è maggiore dell'elemento stesso, nel senso che modifica il flusso della pagina e dei suoi elementi circostanti, alterando quindi direttamente il modo in cui l'elemento si adatta all'interno del suo genitore rispetto ai suoi elementi fratelli. In definitiva un valore di attributo "margin-box" causerebbe gravi problemi ed è essenzialmente lo stesso di impostare direttamente l'altezza / larghezza degli elementi.


1
mi scuso ma non capisco come l'inclusione dell'imbottitura, del bordo e del margine nel calcolo spaziale tramite "margin-box" differisca concettualmente dall'inclusione dell'imbottitura e del bordo tramite "border-box". Sicuramente è solo una variazione sullo stesso tema?
Pancho,

1

Su Codrops ci sono un paio di buoni articoli sull'argomento dell'effetto dei margini e le file sono costrette a traboccare. Suggeriscono di utilizzare l'unità rem o em con un normalizzatore css che imposta la dimensione del carattere al 100% per tutti i browser, quindi quando si impostano larghezze e margini è facile tenere traccia dell'effetto sulla larghezza della riga semplicemente annotando nei commenti per la larghezza totale. Una conversione da 16 px a 1 em è il modo per calcolare il totale delle finestre di destinazione con.

Funzionando in questo modo almeno per lo stadio di sviluppo e quindi se si desidera modelli "reattivi" è possibile convertire le larghezze in% comprese le larghezze dei margini.

L'altro e spesso più semplice modo in cui suggeriscono di gestire le grondaie è usare lo pseudo dopo e l' content: '';uno su ciascuna delle tue colonne che trovo funzioni davvero bene. Se imposti una classe div che è l'ultima colonna definita come end, puoi scegliere come target quella classe per non avere lo pseudo dopo o per averne una più ampia; che si adatta meglio al tuo layout.

Il vantaggio aggiuntivo dell'utilizzo di questo metodo pseudo-elemento è che ti dà anche un bersaglio per le ombre che può dare un effetto più 3d e una maggiore profondità all'immagine piatta sul monitor dei lettori. Al momento sto sperimentando questo effetto aumentando gli effetti utilizzati sui pulsanti, "modificando" i gradienti e l'indice z.


1

Le dimensioni degli elementi a livello di blocco e non sostituiti nel flusso normale devono soddisfare

margine-sinistra + bordo-sinistra-larghezza + imbottitura-sinistra + larghezza + imbottitura-destra + bordo-destra-larghezza + margine-destra = larghezza del blocco contenitore

Se sottoposti a vincoli eccessivi, i browser devono regolare il margine sinistro o destro. Penso che ciò significhi che la larghezza del margine deve essere uguale alla larghezza del blocco contenitore (cioè 100%).

Per il tuo caso, bordi trasparenti con box-sizing: border-boxpossono funzionare in modo molto simile ai margini .


1

Forse imposta il bordo su 0% di opacità usando RGBA e usa il bordo come margine.


Sembra un trucco, ma farebbe il lavoro.
Morgan Feeney,

Questo può rivelarsi utile se non vuoi usare gli involucri per raggiungere il lavoro.
limitlessloop

... a meno che tu non abbia effettivamente bisogno di un confine
FrancescoMM,

@FrancescoMM - un po '"rumoroso", ma potresti creare una scatola con bordo trasparente "margine-larghezza" (e nessun margine ovviamente) e al suo interno posizionare una scatola con un bordo visibile della larghezza che vuoi visualizzare (ancora senza margine)
Pancho

1
Non riesco proprio a seguire questo tipo di pensiero. C'è qualcosa di più naturale del dire che voglio due scatole 1pxseparate, ognuna delle quali occupa lo 50%spazio disponibile? Questo è esattamente ciò che margin-boxfarebbe. Oppure dimentica la casella dei margini e pensa allo spazio disponibile. Non il 50% del contenitore principale, ma il 50% di ciò che resta. Niente "calc", niente "margine del 5%", niente di simile ...
Maaartinus,

0

C'è una situazione interessante quando si usa il ridimensionamento della scatola all'interno del contenuto del corpo

nessun contenuto nessuna casella di confine non fornisce alcun valore sul margine sinistro-destro% di conteggio di questi algoritmi di conteggio con due riquadri

  .body{
    box-sizing: border-box;
    margin:0 3%;
  }

Le versioni di Firefox precedenti alla 57 supportavano anche il valore del riquadro di riempimento per il ridimensionamento del riquadro, sebbene questo valore sia stato rimosso dalle specifiche e dalle versioni successive del browser.

Quindi margin-box anche non pianificato ...

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.