Développez un div pour remplir la largeur restante


552

Je veux une disposition div à deux colonnes, où chacune peut avoir une largeur variable, par exemple

div {
  float: left;
}

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

Je veux que le div «view» s'étende sur toute la largeur disponible après que le div «tree» ait rempli l'espace nécessaire.

Actuellement, ma div «view» est redimensionnée au contenu qu'elle contient. Ce sera également bien si les deux div occupent toute la hauteur.


Clause de non-responsabilité:



1
Soit je ne comprends pas la question, soit je ne comprends pas comment vous choisissez la réponse acceptée, car les largeurs et les hauteurs sont fixées avec l'inconvénient deoverflow hidden
user10089632

Réponses:


1012

La solution à cela est en fait très facile, mais pas du tout évidente. Vous devez déclencher quelque chose appelé un "contexte de formatage de bloc" (BFC), qui interagit avec les flotteurs d'une manière spécifique.

Prenez simplement ce deuxième div, retirez le flotteur et donnez-le à la overflow:hiddenplace. Toute valeur de débordement autre que visible fait que le bloc sur lequel il est défini devient un BFC. Les BFC n'autorisent pas les flotteurs descendants à leur échapper, pas plus qu'ils ne permettent aux flotteurs frères / ancêtres de s'introduire en eux. L'effet net ici est que le div flotté fera son travail, alors le deuxième div sera un bloc ordinaire, occupant toute la largeur disponible sauf celle occupée par le flotteur .

Cela devrait fonctionner sur tous les navigateurs actuels, mais vous devrez peut-être déclencher hasLayout dans IE6 et 7. Je ne m'en souviens pas.

Démos:


28
Excellente réponse! Mais vous vous trompez lorsque vous dites que «toute valeur de débordement autre que automatique» en fera un BFC. Ce que vous voulez dire, c'est que toute valeur de débordement autre que la valeur par défaut (visible) en fera un BFC. En fait, le débordement automatique fonctionne parfaitement aussi - c'est ce que je recommanderais (juste au cas où vous auriez des éléments relativement positionnés qui pourraient sortir de cette division).
BT

52
Cet article a une belle explication: colinaarts.com/articles/the-magic-of-overflow-hidden
Max Cantor

1
Que faire si le contenu est suffisamment volumineux pour déborder la div?
giannis christofakis

11
Il est important de noter que l'ordre des enfants est important. L'élément flottant à largeur fixe doit être au-dessus de l'autre. Il m'a fallu trop de temps pour comprendre pourquoi cela ne fonctionnait pas pour moi avec un changement de commande.
Riplexus du

2
J'ai écrit une réponse expliquant pourquoi un débordement non visible de toutes choses déclenche un BFC, basé sur les réponses données par David et Boris, qui peuvent être trouvées ici: stackoverflow.com/questions/9943503/… Mon interprétation était-elle correcte?
BoltClock

106

Je viens de découvrir la magie des boîtes flexibles (affichage: flex). Essaye ça:

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

Les boîtes flexibles me donnent le contrôle que j'aurais souhaité avoir depuis 15 ans. C'est enfin là! Plus d'informations: https://css-tricks.com/snippets/css/a-guide-to-flexbox/


Je ne sais pas ce que vous avez découvert, mais votre code ne fonctionne pas dans le dernier Chrome jsfiddle.net/fjb548kw/3
Yevgeniy Afanasyev

@YevgeniyAfanasyev J'ai supprimé le "float: left;" pour résoudre le problème. Merci pour la note!
BT

Je vous remercie. Pouvez-vous expliquer pourquoi avez-vous flex-grow: 100;plutôt flex-grow: 1;?
Yevgeniy Afanasyev

2
@YevgeniyAfanasyev Aucune raison particulière sauf que c'est comme ça que j'aime le faire. Cela me permet de penser en pourcentage, donc si je pouvais faire quelque chose comme définir #a sur flex-grow:10et ensuite je définirais #b sur flex-grow: 90#a serait 10% de la largeur de la ligne et #b serait 90% de la largeur de la ligne. Si aucun autre élément n'a un style de largeur flexible, alors peu importe techniquement ce que vous mettez.
BT

cela a fonctionné le mieux pour moi, en essayant de placer une entrée et un bouton côte à côte comme s'ils ne faisaient qu'un.
Souleste

29

Solution Flexbox

C'est à cela que sert la flex-growpropriété.

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>

Remarque: Ajoutez des préfixes de fournisseur flex si requis par les navigateurs pris en charge .


27

Ce serait un bon exemple de quelque chose de trivial à faire avec des tables et difficile (sinon impossible, au moins dans un sens multi-navigateur) à faire avec CSS.

Si les deux colonnes avaient une largeur fixe, ce serait facile.

Si l'une des colonnes avait une largeur fixe, cela serait légèrement plus difficile mais entièrement réalisable.

Avec les deux colonnes à largeur variable, à mon humble avis, vous devez simplement utiliser un tableau à deux colonnes.


11
Le tableau ne sera pas très bon dans un design réactif où vous souhaitez que la colonne de droite glisse sous la gauche sur les petits appareils.
S ..

1
Il existe quelques astuces de conception réactive pour travailler avec les tables: css-tricks.com/responsive-data-tables
Rikki

J'ai tendance à concevoir souvent deux mises en page distinctes complètement et à changer sur un mobile à l'aide de requêtes multimédias.Tout display:none;en étant autant que possible 100% réactif sur une échelle mobile, il est parfois plus agréable de changer complètement votre conception pour un mobile utilisant l'impression tactile. et le style de bouton.
Bysander le

22

Découvrez cette solution

.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
Il s'agit généralement d'une solution supérieure car masquer le débordement n'est pas toujours souhaité.
Joseph Lennox

3
Par OP: "Je veux une disposition div à deux colonnes, où chacune peut avoir une largeur variable". Dans votre réponse, vous devez connaître la largeur de la première colonne, donc ce n'est pas variable. Vous pouvez tout aussi bien définir des largeurs fixes sur les deux colonnes et simplement les faire flotter.
Jacob Alvarez

17

Utilisation 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>

Le problème avec cela est que toutes les largeurs doivent être définies explicitement, soit en tant que valeur (px et em fonctionnent correctement), soit en pourcentage de quelque chose qui se définit explicitement.


15

Ici, cela pourrait aider ...

<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 parce que votre exemple semble fonctionner, mais dans mon scénario réel, la façon dont le contenu de `` vue '' se glisse dans la division `` arbre '', car la division de l'arbre n'est pas à 100%, peut être que javascript le force à être petit et après la hauteur de l'arbre Je vois le contenu de la vue
Anurag Uniyal

Dans ce cas, si vous connaissez la largeur maximale de la colonne de gauche, vous pouvez soit lui donner un style largeur maximale (ne fonctionne pas dans IE) ou penser à margin-left (méfiez-vous des bogues à double marge sur IE) ou rembourrage à gauche.
a6hi5h3k

C'était super! Je l'utilise en ligne comme une solution unique:<div class="clear" style="clear: both; height: 1px; overflow: hidden; font-size:0pt; margin-top: -1px;"></div>
ajwest

5

Je ne comprends pas pourquoi les gens sont prêts à travailler si dur pour trouver une solution pure CSS pour des mises en page simples en colonnes qui sont si faciles à utiliser avec l'ancienne TABLEbalise.

Tous les navigateurs ont toujours la logique de disposition des tableaux ... Appelez-moi peut-être un dinosaure, mais je dis que cela vous aide.

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

Beaucoup moins risqué en termes de compatibilité entre navigateurs également.


2
oui, mais si tout se fait par css pourquoi pas ça, au moins une curiosité si c'est possible?
Anurag Uniyal

2
C'est parce que si vous voulez media-queriesmettre les deux colonnes l'une au-dessus de l'autre dans les petits appareils, c'est impossible avec l'ancienne tablebalise. Pour que cela fonctionne, vous devez appliquer CSSdes styles de tableau. Donc, de nos jours, il est préférable de résoudre ce problème CSSsi vous souhaitez une mise en page réactive pour n'importe quelle taille d'écran.
ElChiniNet

5

Si la largeur de l'autre colonne est fixe, pourquoi ne pas utiliser la calcfonction CSS pour tous les navigateurs courants :

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

De cette façon, la largeur de la deuxième ligne sera calculée (c'est-à-dire la largeur restante) et appliquée en conséquence.


C'est la meilleure réponse en ce qui concerne autre chose que flexbox, comme par exemple css-grid. Fonctionne également avec position: fixedce qui en fait un choix parfait! Je vous remercie!
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>


Je veux quelque chose comme une barre d'état avec des éléments fixes à gauche, des éléments fixes à droite et une ligne de message qui utilise tout l'espace restant. J'ai commencé avec cette réponse et ajouté mon message div APRÈS les flotteurs avec: hauteur: 20px; espace blanc: nowrap; débordement caché; text-overflow: clip
englebart

3

Vous pouvez essayer la disposition de grille CSS .

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 - Ceci définit la capacité d'un élément flex à se développer si nécessaire. Il accepte une valeur sans unité qui sert de proportion. Il dicte la quantité d'espace disponible à l'intérieur du conteneur flexible que l'article doit occuper.

Si la flex-croissance est réglée sur 1 pour tous les articles, l'espace restant dans le conteneur sera distribué également à tous les enfants. Si l'un des enfants a une valeur de 2, l'espace restant occuperait deux fois plus d'espace que les autres (ou il essaiera, au moins). Voir plus ici

.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

Une implémentation légèrement différente,

Deux panneaux div (contenu + supplémentaire), côte à côte, se content paneldéveloppent s'ils extra panelne sont pas présents.

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


1

Pat - Tu as raison. C'est pourquoi cette solution satisferait à la fois les «dinosaures» et les contemporains. :)

.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
Il n'y a pas de référence html pour la classe css .ip et cela ne fonctionne pas dans IE7
Keith K

1

Vous pouvez utiliser la bibliothèque CSS de W3 qui contient une classe appelée restqui fait exactement cela:

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

N'oubliez pas de lier la bibliothèque CSS dans la page header:

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

Voici la démo officielle: W3 School Tryit Editor


On dirait que cela ajoute juste "overflow: hidden", ce qui en fait une pire version de la réponse déjà donnée
vpzomtrrfrt

0

Je ne sais pas si c'est la réponse à laquelle vous vous attendez, mais pourquoi ne définissez-vous pas la largeur de l'arbre sur 'auto' et la largeur de 'vue' sur 100%?


3
Parce que cela mettra le deuxième flotteur en dessous du premier parce qu'il est trop large.
cletus

0

Jetez un œil aux frameworks de disposition CSS disponibles. Je recommanderais Simpl ou, le cadre Blueprint un peu plus complexe.

Si vous utilisez Simpl (qui implique d'importer un seul fichier simpl.css ), vous pouvez le faire:

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

, pour une mise en page 50-50, ou:

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

, pour un 25-75.

C'est si simple.


les deux colonnes auront-elles une largeur variable?
Anurag Uniyal,

0

Merci pour la prise de Simpl.css!

n'oubliez pas d'envelopper toutes vos colonnes ColumnWrappercomme ça.

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

Je suis sur le point de publier la version 1.0 de Simpl.css, alors aidez à passer le mot!


0

J'ai écrit une fonction javascript que j'appelle depuis jQuery $ (document) .ready (). Cela analysera tous les enfants de la division parent et ne mettra à jour que l'enfant le plus à droite.

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

C'est assez facile à utiliser avec flexbox. Voir l'extrait ci-dessous. J'ai ajouté un conteneur wrapper pour contrôler le flux et définir une hauteur globale. Des frontières ont également été ajoutées pour identifier les éléments. Notez que les divs se développent désormais également sur toute la hauteur, selon les besoins. Les préfixes du fournisseur doivent être utilisés pour flexbox dans un scénario réel car il n'est pas encore entièrement pris en charge.

J'ai développé un outil gratuit pour comprendre et concevoir des mises en page à l'aide de flexbox. Découvrez-le ici: 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>


avez-vous lu TOUTES les réponses précédentes avant d'ajouter la vôtre? il semble que non ...
Temani Afif

en remarque, vous n'avez pas besoin d'ajouter stretchcar c'est la valeur par défaut et pas besoin de rendre le conteneur flexible de l'élément enfant donc il display:flexest inutile pour les éléments intérieurs
Temani Afif

Je me demande pourquoi le downvote, sans aucun commentaire. Cette réponse ne répond-elle pas à la question? Pourquoi? Si essayer d'aider les autres est pénalisé, j'y réfléchirai à deux fois avant ma prochaine réponse,
Mario Vázquez

1
vous avez obtenu deux commentaires après le downvote, ce n'est pas suffisant?
Temani Afif

Temari, Avez-vous vérifié mon outil? Ne pensez-vous pas utile et pourrait aider les autres? Pensez-vous que ce n'est pas lié à la question? Quelle est votre réponse à cette question? Je ne le vois pas. Quel est ton rôle ici?
Mario Vázquez

-3

Si les deux largeurs sont de longueur variable, pourquoi ne calculez-vous pas la largeur avec certains scripts ou côté serveur?

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

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

3
Comment le serveur sait-il comment fonctionnera le moteur de mise en page du client?
Kev

Simple: développez-le pour 90% des navigateurs :) IE 7+, FF3 + et Safari supportent CSS 3. Vous pouvez également inclure l'élément standard IE6 <! - [if lte IE 6]>. Soit dit en passant, quel navigateur ne prend pas en charge style = "width:%" ??
amischiefr

Je ne sais pas comment cela peut être fait côté serveur, mais oui, certains javscript peuvent le faire, mais je veux l'éviter à moins que css / html ne puisse pas le faire
Anurag Uniyal

Ce qu'il ne peut pas. Par conséquent, si vous voulez que les deux soient dynamiques, vous devez le faire côté script ou côté serveur.
amischiefr
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.