Espandi un div per riempire la larghezza rimanente


552

Voglio un layout div a due colonne, dove ognuno può avere una larghezza variabile, ad es

div {
  float: left;
}

.second {
  background: #ccc;
}
<div>Tree</div>
<div class="second">View</div>

Voglio che il div "view" si espanda per l'intera larghezza disponibile dopo che il div "tree" ha riempito lo spazio necessario.

Attualmente, il mio div "view" viene ridimensionato in base al contenuto in esso contenuto. Sarà anche utile se entrambi i div occupano l'intera altezza.


Disclaimer non duplicato:



1
O non capisco la domanda o non capisco come si sceglie la risposta accettata, perché sia ​​le larghezze che le altezze sono state overflow hidden
risolte

Risposte:


1012

La soluzione a questo è in realtà molto semplice, ma per nulla ovvia. Devi attivare qualcosa chiamato "block formatting context" (BFC), che interagisce con i float in un modo specifico.

Basta prendere quel secondo div, rimuovere il galleggiante e darlo overflow:hiddeninvece. Qualsiasi valore di overflow diverso da quello visibile rende il blocco su cui è impostato diventa un BFC. I BFC non consentono ai galleggianti discendenti di sfuggirli, né permettono ai galleggianti fratelli / antenati di intromettersi. L'effetto netto qui è che il div fluttuante farà la sua cosa, quindi il secondo div sarà un blocco ordinario, occupando tutta la larghezza disponibile tranne quella occupata dal float .

Questo dovrebbe funzionare su tutti i browser attuali, anche se potrebbe essere necessario attivare hasLayout in IE6 e 7. Non riesco a ricordare.

Demos:


28
Risposta eccellente! Ma ti sbagli quando dici "qualsiasi valore di overflow diverso da auto" lo renderà un BFC. Quello che vuoi dire è che qualsiasi valore di overflow diverso da quello predefinito (visibile) lo renderà un BFC. In effetti, anche l'overflow automatico funziona perfettamente - questo è quello che consiglierei (nel caso in cui tu abbia elementi relativamente posizionati che potrebbero sbirciare da quel div).
BT,

52
Questo articolo ha una bella spiegazione: colinaarts.com/articles/the-magic-of-overflow-hidden
Max Cantor

1
Cosa succede se il contenuto è abbastanza grande da traboccare il div?
giannis christofakis,

11
È importante notare che l'ordine dei bambini è importante. L'elemento flottante con larghezza fissa deve essere sopra l'altro. Mi ci è voluto troppo tempo per capire, perché non ha funzionato per me con ordine cambiato.
Riplexus,

2
Ho scritto una risposta spiegando perché un overflow non visibile di tutte le cose innesca un BFC, basato sulle risposte fornite da David e Boris, che può essere trovato qui: stackoverflow.com/questions/9943503/… La mia interpretazione era corretta?
BoltClock

106

Ho appena scoperto la magia delle scatole flessibili (display: flex). Prova questo:

<style>
  #box {
    display: flex;
  }
  #b {
    flex-grow: 100;
    border: 1px solid green;
  }
</style>
<div id='box'>
 <div id='a'>Tree</div>
 <div id='b'>View</div>
</div>

Le scatole flessibili mi danno il controllo che avrei voluto avere per 15 anni. È finalmente arrivato! Maggiori informazioni: https://css-tricks.com/snippets/css/a-guide-to-flexbox/


Non so cosa hai scoperto, ma il tuo codice non funziona nell'ultimo Chrome jsfiddle.net/fjb548kw/3
Yevgeniy Afanasyev

@YevgeniyAfanasyev Ho rimosso il "float: left;" per risolvere il problema. Grazie per la nota!
BT,

Grazie. Puoi spiegare perché hai flex-grow: 100;invece di flex-grow: 1;?
Yevgeniy Afanasyev

2
@YevgeniyAfanasyev Nessun motivo particolare tranne che è come mi piace farlo. Mi permette di pensare in percentuale, quindi se potessi fare qualcosa come impostare #a su flex-grow:10e quindi impostare #b su flex-grow: 90così #a sarebbe il 10% della larghezza della linea e #b sarebbe il 90% della larghezza della linea. Se nessun altro elemento ha uno stile di larghezza flessibile, non importa tecnicamente ciò che metti.
BT

questo ha funzionato meglio per me, cercando di posizionare un input e un pulsante fianco a fianco come se fossero uno.
Souleste

29

Soluzione Flexbox

Ecco a cosa serve la flex-growproprietà.

html, body {
  height: 100%;
}
body {
  display: flex;
}
.second {
  flex-grow: 1;
}
<div style="background: #bef;">Tree</div>
<div class="second" style="background: #ff9;">View</div>

Nota: aggiungere prefissi fornitore flessibili se richiesto dai browser supportati .


27

Questo sarebbe un buon esempio di qualcosa che è banale da fare con le tabelle e difficile (se non impossibile, almeno in senso trasversale) con i CSS.

Se entrambe le colonne avessero una larghezza fissa, sarebbe facile.

Se una delle colonne avesse una larghezza fissa, sarebbe leggermente più difficile ma del tutto fattibile.

Con entrambe le colonne di larghezza variabile, IMHO è sufficiente utilizzare una tabella a due colonne.


11
La tabella non sarà molto buona in un design reattivo in cui vuoi che la colonna di destra scorra sotto la sinistra su piccoli dispositivi.
S ..

1
Ci sono alcuni trucchi di progettazione reattiva per lavorare con le tabelle: css-tricks.com/responsive-data-tables
Rikki

Tendo ora a progettare spesso due layout separati completamente e a cambiarli su un dispositivo mobile usando media query e, display:none;sebbene sia il più possibile reattivo al 100% su una scala mobile, a volte è più bello cambiare completamente il tuo design per un dispositivo mobile sfruttando la sensazione del touchscreen e stile pulsante.
Bysander

22

Dai un'occhiata a questa soluzione

.container {
  width: 100%;
  height: 200px;
  background-color: green;
}
.sidebar {
  float: left;
  width: 200px;
  height: 200px;
  background-color: yellow;
}
.content {
  background-color: red;
  height: 200px;
  width: auto;
  margin-left: 200px;
}
.item {
  width: 25%;
  background-color: blue;
  float: left;
  color: white;
}
.clearfix {
  clear: both;
}
<div class="container">
  <div class="clearfix"></div>
  <div class="sidebar">width: 200px</div>

  <div class="content">
    <div class="item">25%</div>
    <div class="item">25%</div>
    <div class="item">25%</div>
    <div class="item">25%</div>
  </div>
</div>


2
Questa è generalmente una soluzione superiore perché non è sempre necessario nascondere l'overflow.
Joseph Lennox,

3
Per OP: "Voglio un layout div a due colonne, in cui ognuno può avere una larghezza variabile". Nella tua risposta, devi conoscere la larghezza della prima colonna, quindi non è variabile. Puoi anche impostare larghezze fisse su entrambe le colonne e semplicemente fluttuare.
Jacob Alvarez,

17

Utilizzare calc:

.leftSide {
  float: left;
  width: 50px;
  background-color: green;
}
.rightSide {
  float: left;
  width: calc(100% - 50px);
  background-color: red;
}
<div style="width:200px">
  <div class="leftSide">a</div>
  <div class="rightSide">b</div>
</div>

Il problema è che tutte le larghezze devono essere definite in modo esplicito, sia come valore (px ed em funzionano bene), sia come percentuale di qualcosa che si definisce esplicitamente.


15

Qui, questo potrebbe aiutare ...

<html>

<head>
  <style type="text/css">
    div.box {
      background: #EEE;
      height: 100px;
      width: 500px;
    }
    div.left {
      background: #999;
      float: left;
      height: 100%;
      width: auto;
    }
    div.right {
      background: #666;
      height: 100%;
    }
    div.clear {
      clear: both;
      height: 1px;
      overflow: hidden;
      font-size: 0pt;
      margin-top: -1px;
    }
  </style>
</head>

<body>
  <div class="box">
    <div class="left">Tree</div>
    <div class="right">View</div>
    <div class="clear" />
  </div>
</body>

</html>


+1 perché il tuo esempio sembra funzionare, ma nel mio scenario reale alcuni come i contenuti di 'view' si insinuano nel div 'tree', poiché il div dell'albero non è al 100%, potrebbe essere un po 'di javascript che lo costringe a essere piccolo e dopo l'altezza dell'albero Vedo i contenuti della vista
Anurag Uniyal,

In tal caso, se conosci la larghezza massima della colonna di sinistra, puoi dargli uno stile di larghezza massima (non funziona in IE) o pensare a margine-sinistra (attenzione ai bug a doppio margine su IE) o padding-left.
a6hi5h3k,

Questo è stato fantastico! Lo sto usando in linea come soluzione unica:<div class="clear" style="clear: both; height: 1px; overflow: hidden; font-size:0pt; margin-top: -1px;"></div>
ajwest

5

Non capisco perché le persone siano disposte a lavorare così duramente per trovare una soluzione pure-CSS per semplici layout a colonne che siano COSÌ FACILI usando il vecchio TABLEtag.

Tutti i browser hanno ancora la logica del layout del tavolo ... Forse chiamami dinosauro, ma dico che ti aiuti.

<table WIDTH=100% border=0 cellspacing=0 cellpadding=2>
  <tr>
    <td WIDTH="1" NOWRAP bgcolor="#E0E0E0">Tree</td>
    <td bgcolor="#F0F0F0">View</td>
  </tr>
</table>

Molto meno rischioso anche in termini di compatibilità tra browser.


2
si, ma se css sta facendo tutto, perché no, almeno una curiosità se è possibile?
Anurag Uniyal

2
Questo perché se vuoi media-queriesmettere entrambe le colonne una sopra l'altra in piccoli dispositivi, è impossibile con il vecchio tabletag. Per farlo funzionare, è necessario applicare gli CSSstili di tabella. Quindi, per oggi è meglio risolverlo con CSSse si desidera un layout reattivo per qualsiasi dimensione dello schermo.
ElChiniNet,

5

Se la larghezza dell'altra colonna è fissa, che ne dici di usare la calcfunzione CSS funzionante per tutti i browser comuni :

width: calc(100% - 20px) /* 20px being the first column's width */

In questo modo verrà calcolata la larghezza della seconda riga (ovvero la larghezza rimanente) e applicata in modo reattivo.


Questa è la risposta migliore per quanto riguarda l'utilizzo di qualsiasi altra cosa che non sia flexbox, come ad esempio css-grid. Funziona anche con il position: fixedquale rende la scelta perfetta! Grazie!
Bartekus,

3

<html>

<head>
  <style type="text/css">
    div.box {
      background: #EEE;
      height: 100px;
      width: 500px;
    }
    div.left {
      background: #999;
      float: left;
      height: 100%;
      width: auto;
    }
    div.right {
      background: #666;
      height: 100%;
    }
    div.clear {
      clear: both;
      height: 1px;
      overflow: hidden;
      font-size: 0pt;
      margin-top: -1px;
    }
  </style>
</head>

<body>
  <div class="box">
    <div class="left">Tree</div>
    <div class="right">View</div>
    <div class="right">View</div>
    <div style="width: <=100% getTreeWidth()100 %>">Tree</div>
    <div class="clear" />
  </div>
  <div class="ColumnWrapper">
    <div class="Colum­nOne­Half">Tree</div>
    <div class="Colum­nOne­Half">View</div>
  </div>

</body>

</html>


Voglio qualcosa come una barra di stato con elementi fissi a sinistra, elementi fissi a destra e una riga di messaggio che utilizza tutto lo spazio a sinistra. Ho iniziato con questa risposta e ho aggiunto il mio messaggio div DOPO i float con: height: 20px; white-space: nowrap; troppo pieno: nascosto; text-overflow: clip
englebart

3

Puoi provare CSS Grid Layout .

dl {
  display: grid;
  grid-template-columns: max-content auto;
}

dt {
  grid-column: 1;
}

dd {
  grid-column: 2;
  margin: 0;
  background-color: #ccc;
}
<dl>
  <dt>lorem ipsum</dt>
  <dd>dolor sit amet</dd>
  <dt>carpe</dt>
  <dd>diem</dd>
</dl>


2

flex-grow: definisce la capacità di crescita di un articolo flessibile, se necessario. Accetta un valore senza unità che funge da proporzione. Determina la quantità di spazio disponibile all'interno del contenitore flessibile che l'oggetto dovrebbe occupare.

Se tutti gli articoli hanno flex-grow impostato su 1, lo spazio rimanente nel contenitore verrà distribuito equamente a tutti i bambini. Se uno dei bambini ha un valore di 2, lo spazio rimanente occuperebbe il doppio dello spazio degli altri (o almeno proverà a farlo). Vedi di più qui

.parent {
  display: flex;
}

.child {
  flex-grow: 1; // It accepts a unitless value that serves as a proportion
}

.left {
  background: red;
}

.right {
  background: green;
}
<div class="parent"> 
  <div class="child left">
      Left 50%
  </div>
   <div class="child right">
      Right 50%
  </div>
</div>


1

Un'attuazione leggermente diversa,

Due pannelli div (contenuto + extra), fianco a fianco, si content panelespandono se extra panelnon sono presenti.

jsfiddle: http://jsfiddle.net/qLTMf/1722/


1

Pat - Hai ragione. Ecco perché questa soluzione soddisfa sia i "dinosauri" che i contemporanei. :)

.btnCont {
  display: table-layout;
  width: 500px;
}

.txtCont {
  display: table-cell;
  width: 70%;
  max-width: 80%;
  min-width: 20%;
}

.subCont {
  display: table-cell;
  width: 30%;
  max-width: 80%;
  min-width: 20%;
}
<div class="btnCont">
  <div class="txtCont">
    Long text that will auto adjust as it grows. The best part is that the width of the container would not go beyond 500px!
  </div>
  <div class="subCont">
    This column as well as the entire container works like a table. Isn't Amazing!!!
  </div>
</div>


2
Non esiste un riferimento html per la classe css .ip e non funziona in IE7
Keith K

1

Puoi usare la libreria CSS di W3 che contiene una classe chiamata restche fa proprio questo:

<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">

<div class="w3-row">
  <div class="w3-col " style="width:150px">
    <p>150px</p>
  </div>
  <div class="w3-rest w3-green">
    <p>w3-rest</p>
  </div>
</div>

Non dimenticare di collegare la libreria CSS nella pagina header:

<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">

Ecco la demo ufficiale: W3 School Tryit Editor


Sembra che aggiunge semplicemente "overflow: hidden", il che rende una versione peggiore della risposta già fornita
vpzomtrrfrt

0

Non sono sicuro se questa è la risposta che ti aspetti, ma perché non impostare la larghezza dell'albero su "auto" e la larghezza di "Visualizza" al 100%?


3
Perché questo metterà il secondo float sotto il primo perché è troppo largo.
cletus,

0

Dai un'occhiata ai framework di layout CSS disponibili. Consiglierei Simpl o, il framework Blueprint leggermente più complesso.

Se stai usando Simpl (che implica l'importazione di un solo file simpl.css ), puoi farlo:

<div class="Colum­nOne­Half">Tree</div>
<div class="Colum­nOne­Half">View</div>

, per un layout 50-50 o:

<div class="Colum­nOne­Quarter">Tree</div>
<div class="Colum­nThreeQuarters">View</div>

, per 25-75.

È così semplice.


entrambe le colonne avranno larghezza variabile?
Anurag Uniyal,

0

Grazie per la spina di Simpl.css!

ricordati di avvolgere tutte le colonne in questo ColumnWrappermodo.

<div class="ColumnWrapper">
    <div class="Colum­nOne­Half">Tree</div>
    <div class="Colum­nOne­Half">View</div>
</div>

Sto per rilasciare la versione 1.0 di Simpl.css quindi aiutate a spargere la voce!


0

Ho scritto una funzione JavaScript che chiamo da jQuery $ (document) .ready (). Questo analizzerà tutti i figli del div genitore e aggiornerà solo il figlio più giusto.

html

...
<div class="stretch">
<div style="padding-left: 5px; padding-right: 5px; display: inline-block;">Some text
</div>
<div class="underline" style="display: inline-block;">Some other text
</div>
</div>
....

javascript

$(document).ready(function(){
    stretchDivs();
});

function stretchDivs() {
    // loop thru each <div> that has class='stretch'
    $("div.stretch").each(function(){
        // get the inner width of this <div> that has class='stretch'
        var totalW = parseInt($(this).css("width"));
        // loop thru each child node
        $(this).children().each(function(){
            // subtract the margins, borders and padding
            totalW -= (parseInt($(this).css("margin-left")) 
                     + parseInt($(this).css("border-left-width")) 
                     + parseInt($(this).css("padding-left"))
                     + parseInt($(this).css("margin-right")) 
                     + parseInt($(this).css("border-right-width")) 
                     + parseInt($(this).css("padding-right")));
            // if this is the last child, we can set its width
            if ($(this).is(":last-child")) {
                $(this).css("width","" + (totalW - 1 /* fudge factor */) + "px");
            } else {
                // this is not the last child, so subtract its width too
                totalW -= parseInt($(this).css("width"));
            }
        });
    });
}

0

Questo è abbastanza facile usando flexbox. Vedi lo snippet di seguito. Ho aggiunto un contenitore wrapper per controllare il flusso e impostare un'altezza globale. Sono stati aggiunti anche i bordi per identificare gli elementi. Si noti che ora anche i div si espandono a tutta altezza, come richiesto. I prefissi del fornitore devono essere utilizzati per flexbox in uno scenario del mondo reale poiché non è ancora completamente supportato.

Ho sviluppato uno strumento gratuito per comprendere e progettare layout usando flexbox. Dai un'occhiata qui: http://algid.com/Flex-Designer

.container{
    height:180px;
    border:3px solid #00f;
    display:flex;
    align-items:stretch;
}
div {
    display:flex;
    border:3px solid #0f0;
}
.second {
    display:flex;
    flex-grow:1;
    border:3px solid #f00;
}
<div class="container">
    <div>Tree</div>
    <div class="second">View</div>
</div>


hai letto TUTTE le risposte precedenti prima di aggiungere le tue? sembra di no ...
Temani dopo il

come nota a margine, non è necessario aggiungere stretchperché è il valore predefinito e non è necessario rendere flessibile il contenitore degli elementi figlio, quindi display:flexè inutile per gli elementi interni
Temani Afif

Mi chiedo perché il downvote, senza alcun commento. Questa risposta non risponde alla domanda? Perché? Se cercare di aiutare gli altri è penalizzato, ci penserò due volte prima della mia prossima risposta,
Mario Vázquez,

1
hai ricevuto due commenti dopo il downvote, non è abbastanza?
Temani Afif,

Temari, hai controllato il mio strumento? Non pensi che sia utile e possa aiutare gli altri? Pensi che non sia correlato alla domanda? Dov'è la tua risposta a questa domanda? Non riesco a vederlo Qual è il tuo ruolo qui?
Mario Vázquez,

-3

Se entrambe le larghezze sono di lunghezza variabile, perché non calcolare la larghezza con alcuni script o lato server?

<div style="width: <=% getTreeWidth() %>">Tree</div>

<div style="width: <=% getViewWidth() %>">View</div>

3
Come fa il server a sapere come funzionerà il motore di layout del client?
Kev

Semplice: sviluppalo per il 90% dei browser disponibili :) IE 7+, FF3 + e Safari supportano CSS 3. Potresti anche includere l'elemento standard IE6 <! - [if lte IE 6]>. A proposito, quale browser non supporta style = "width:%" ??
amischiefr,

Non so come si possa fare sul lato server, ma sì, alcuni javscript potrebbero farlo ma voglio evitarlo a meno che css / html non riescano a farlo
Anurag Uniyal

Che non può. Pertanto, se si desidera che entrambi siano dinamici, è necessario farlo nel lato script o lato server.
amischiefr,
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.