Come fare in modo che un elemento di blocco inline riempia il resto della linea?


186

È possibile utilizzare CSS e due tag DIV a blocco inline (o qualsiasi altra cosa) invece di utilizzare una tabella?

La versione della tabella è questa (bordi aggiunti in modo da poterlo vedere):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head></head>
<body>
<table style="width:100%;">
<tr>
<td style="border:1px solid black;width:100px;height:10px;"></td>
<td style="border:1px solid black;height:10px;"></td>
</tr>
</table>
</body>
</html>

Produce una colonna sinistra con una LARGHEZZA FISSA (non una larghezza percentuale) e una colonna destra che si espande per riempire LO SPAZIO RIMANENTE sulla linea. Sembra abbastanza semplice, vero? Inoltre, poiché nulla viene "flottato", l'altezza del contenitore principale si espande correttamente per comprendere l'altezza del contenuto.

--BEGIN RANT--
Ho visto le implementazioni "clear fix" e "holy grail" per layout multi-colonna con colonna laterale a larghezza fissa, e fanno schifo e sono complicate. Invertono l'ordine degli elementi, usano larghezze percentuali o usano float, margini negativi e la relazione tra gli attributi "sinistra", "destra" e "margine" è complessa. Inoltre, i layout sono sensibili ai sub-pixel in modo che l'aggiunta di un solo pixel di bordi, riempimento o margini interrompa l'intero layout e invii intere colonne alla riga successiva. Ad esempio, gli errori di arrotondamento sono un problema anche se si tenta di fare qualcosa di semplice, come mettere 4 elementi su una linea, con la larghezza di ognuno impostata al 25%.
--END RANT--

Ho provato a usare "inline-block" e "white-space: nowrap;", ma il problema è che non riesco proprio a ottenere il 2 ° elemento per riempire lo spazio rimanente sulla linea. L'impostazione della larghezza su "larghezza: 100% - (LeftColumWidth) px" funzionerà in alcuni casi, ma l'esecuzione di un calcolo in una proprietà di larghezza non è realmente supportata.


1
Non penso che ci sia un modo sano per farlo, tranne quello di trasformarlo in un display: table-*costrutto che funzionerà, ma non è nemmeno "più semantico" (essendo un terribile caso di divzuppa) e rompe la compatibilità con IE6. Personalmente mi atterrei a <table>, a meno che qualcuno non riesca a trovare un'idea geniale semplice che funzioni senza
Pekka

51
Si. Continuo a imbattermi in tutti questi argomenti di "evitare le tabelle" dagli albori dell'era CSS, e sono formulati per farti sembrare un deficiente pigro incompetente se usi ancora le tabelle per i layout. Avanti veloce di un decennio, ed è ancora un sogno idealistico. Il fatto è che la semantica del layout di flusso SUCK per layout fissi ma flessibili come interfacce utente e moduli. La verità è che le persone intelligenti useranno le tabelle nel modo più conveniente, perché hanno esaurito ogni possibile soluzione CSS e si sono rese conto che sono tutte imperfette e significativamente più complesse rispetto al semplice utilizzo di una tabella.
Triynko,

4
Galleggianti? Mostrami il codice di lavoro, in cui gli elementi di fine riga non si avvolgono in modo imprevedibile e bordi e margini non interrompono il layout. Questo è ciò che non va in loro. Inoltre, il contenitore padre di dimensioni automatiche si espande correttamente per includere elementi mobili senza gli hack "clear fix"? Non la pensavo così.
Triynko,

Se hai almeno un elemento non float nel tuo contenitore genitore, allora non è davvero un "hack" per cancellare i float, adesso? Ricorda che il CSS ha le sue radici nella stampa - vedi css-tricks.com/containers-dont-clear-floats per una buona discussione del perché non ottieni l'autorizzazione automatica.
Chowlett,

3
@Triynko: Questo è quello che ho fatto prima: jsfiddle.net/thirtydot/qx32C - Penso che colpisca la maggior parte dei tuoi punti. Ascolterò la tua critica di quella demo che ho fatto e proverò a risolverlo in seguito.
trenta,

Risposte:


169

Vedi: http://jsfiddle.net/qx32C/36/

.lineContainer {
    overflow: hidden; /* clear the float */
    border: 1px solid #000
}
.lineContainer div {
    height: 20px
} 
.left {
    width: 100px;
    float: left;
    border-right: 1px solid #000
}
.right {
    overflow: hidden;
    background: #ccc
}
<div class="lineContainer">
    <div class="left">left</div>
    <div class="right">right</div>
</div>


Perché ho sostituito margin-left: 100pxcon overflow: hiddenon .right?

EDIT: Ecco due mirror per il link precedente (morto):


60
Se ti definisci uno sviluppatore web, devi fare clic su quel link. L'ho fatto e mi sono sentito proprio come Jasmine in un giro magico sul tappeto.
Chris Shouts,

2
@ChrisShouts, questo è probabilmente il modo migliore per descriverlo. Questo metodo non ha senso, ma poi di nuovo ... Una soluzione alternativa meravigliosa per qualcosa che dovresti essere in grado di fare esplicitamente.
mjvotaw,

14
L'overflow nascosto non è una soluzione. Supponiamo di non voler nascondere l'overflow del contenitore giusto. Questo non fa in modo che la dimensione del contenitore giusto riempia lo spazio rimanente sulla linea. Questo è un esempio di una domanda di due anni per la quale non ho ancora segnato una risposta, perché non esiste ancora una risposta soddisfacente.
Triynko

3
Triynko: anche se stai usando 'overflow: hidden', nulla sarà generalmente nascosto (almeno se hai solo del testo). Il testo / gli elementi all'interno del div verranno disposti in modo da adattarsi all'interno del div (ovviamente, a meno che tu non abbia un elemento più grande del div).
CpnCrunch

1
@RMorrisey: Probabilmente solo bisogno di qualche box-sizing: border-boxsulle divs. Solo una supposizione, dal momento che non hai fornito una demo che mostra il comportamento che descrivi. Detto questo, la display: tablesoluzione basata su di solito è migliore . Questa è una domanda molto antica, ma penso che stavo cercando di evitare qualsiasi cosa abbia a che fare con le tabelle in questa domanda a causa del comportamento di OP.
trenta,

65

Una soluzione moderna che utilizza flexbox:

.container {
    display: flex;
}
.container > div {
    border: 1px solid black;
    height: 10px;
}

.left {
   width: 100px;
}

.right {
    width: 100%;
    background-color:#ddd;
}
<div class="container">
  <div class="left"></div>
  <div class="right"></div>
</div>

http://jsfiddle.net/m5Xz2/100/


4
display flex e larghezza 100% .. devo ricordare
dreamerkumar il

10
quando si utilizza flex, perché non utilizzare al flex: 1posto di width: 100%?
Itai Bar-Haim,

Per chi non conosce Flexbox : flex: 1è una scorciatoia per flex-grow: 1. Si tratta di un attributo combinazione: flex: <grow> <shrink> <basis>.
tanius

1
Solo una breve nota che mostra: flex non è supportato in IE <11, e molto buggy in 11.
Eric Shields

1
@EricShields non dovrebbe impedire a nessuno di usare Flexbox. Oggi lo flexbugssappiamo.
Neurotrasmettitore

47

Compatibile con i browser moderni più comuni (IE 8+): http://jsfiddle.net/m5Xz2/3/

.lineContainer {
    display:table;
    border-collapse:collapse;
    width:100%;
}
.lineContainer div {
    display:table-cell;
    border:1px solid black;
    height:10px;
}
.left {
    width:100px;
}
 <div class="lineContainer">
    <div class="left">left</div>
    <div class="right">right</div>
</div>


9
L'argomento contro l'utilizzo delle tabelle non ha nulla a che fare con le sue caratteristiche di presentazione. Ha a che fare con markup ingestibili, confusione di stile / documento e semantica impropria. Nessuno di questi argomenti si applica a display:table.
Rich Remer,

Questo non risponde come inline-blockriempire il resto della riga.
Neurotrasmettitore

1
@TranslucentCloud Sono d'accordo sul fatto che la mia risposta non risponde esattamente al titolo della domanda, ma fornisce un modo per riempire la larghezza disponibile usando div, come richiesto nel corpo della domanda.
Frosty Z,

1
Mi piace molto questa soluzione. Non sei forzato a usare alcuni stili strani che derivano dalla logica CSS nascosta (come per l'overflow nascosto).
Chaoste,

4

È possibile utilizzare calc (100% - 100px) sull'elemento fluido, insieme a display: blocco in linea per entrambi gli elementi.

Ricorda che non ci dovrebbe essere spazio tra i tag, altrimenti dovrai considerare anche quello spazio nel tuo calc.

.left{
    display:inline-block;
    width:100px;
}
.right{
    display:inline-block;
    width:calc(100% - 100px);
}


<div class=“left”></div><div class=“right”></div>

Esempio rapido: http://jsfiddle.net/dw689mt4/1/


1

Ho usato la flex-growproprietà per raggiungere questo obiettivo. Dovrai impostare display: flexper il contenitore principale, quindi devi impostare flex-grow: 1per il blocco che vuoi riempire lo spazio rimanente, o proprio flex: 1come tanius menzionato nei commenti.


0

Se non puoi usare overflow: hidden(perché non vuoi overflow: hidden) o se non ti piacciono gli hack / soluzioni alternative CSS, puoi usare JavaScript. Si noti che potrebbe non funzionare anche perché è JavaScript.

var parent = document.getElementsByClassName("lineContainer")[0];
var left = document.getElementsByClassName("left")[0];
var right = document.getElementsByClassName("right")[0];
right.style.width = (parent.offsetWidth - left.offsetWidth) + "px";
window.onresize = function() {
  right.style.width = (parent.offsetWidth - left.offsetWidth) + "px";
}
.lineContainer {
  width: 100% border: 1px solid #000;
  font-size: 0px;
  /* You need to do this because inline block puts an invisible space between them and they won't fit on the same line */
}

.lineContainer div {
  height: 10px;
  display: inline-block;
}

.left {
  width: 100px;
  background: red
}

.right {
  background: blue
}
<div class="lineContainer">
  <div class="left"></div>
  <div class="right"></div>
</div>

http://jsfiddle.net/ys2eogxm/


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.