Expande un div para llenar el ancho restante

552

Quiero un diseño div de dos columnas, donde cada uno puede tener un ancho variable, por ejemplo

div {
  float: left;
}

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

Quiero que el div 'vista' se expanda a todo el ancho disponible después de que el div 'árbol' haya llenado el espacio necesario.

Actualmente, mi div "vista" cambia de tamaño al contenido que contiene. También será bueno si ambos div ocupan toda la altura.


Descargo de responsabilidad no duplicado:

Anurag Uniyal
fuente
1
stackoverflow
Adrien Be
1
O no entiendo la pregunta o no entiendo cómo elige la respuesta aceptada, porque tanto los anchos como las alturas se arreglan con el inconveniente deoverflow hidden
user10089632

Respuestas:

1012

La solución a esto es realmente muy fácil, pero en absoluto obvia. Debe activar algo llamado "contexto de formato de bloque" (BFC), que interactúa con los flotantes de una manera específica.

Solo toma ese segundo div, quita el flotador y dale en su overflow:hiddenlugar. Cualquier valor de desbordamiento que no sea visible hace que el bloque en el que está configurado se convierta en un BFC. Los BFC no permiten que los flotadores descendientes escapen de ellos, ni permiten que los flotadores de hermanos / antepasados ​​se entrometan en ellos. El efecto neto aquí es que el div flotante hará lo suyo, luego el segundo div será un bloque ordinario, ocupando todo el ancho disponible, excepto el ocupado por el flotador .

Esto debería funcionar en todos los navegadores actuales, aunque es posible que deba activar hasLayout en IE6 y 7. No puedo recordarlo.

Población:

Xanthir
fuente
28
Excelente respuesta! Pero se equivoca cuando dice "cualquier valor de desbordamiento que no sea automático" lo convertirá en un BFC. Lo que quiere decir es que cualquier valor de desbordamiento que no sea el predeterminado (visible) lo convertirá en un BFC. De hecho, el desbordamiento automático también funciona perfectamente, eso es lo que recomendaría (en caso de que tenga elementos relativamente posicionados que puedan asomarse desde ese div).
BT
52
Este artículo tiene una buena explicación: colinaarts.com/articles/the-magic-of-overflow-hidden
Max Cantor
1
¿Qué pasa si el contenido es lo suficientemente grande como para desbordar el div?
giannis christofakis
11
Es importante tener en cuenta que el orden de los niños es importante. El elemento flotante con ancho fijo debe estar por encima del otro. Me tomó demasiado tiempo entender por qué no me funcionó con el orden cambiado.
Riplexus
2
Escribí una respuesta explicando por qué un desbordamiento no visible de todas las cosas desencadena un BFC, basado en las respuestas dadas por David y Boris, que se pueden encontrar aquí: stackoverflow.com/questions/9943503/... ¿Fue correcta mi interpretación?
BoltClock
106

Acabo de descubrir la magia de las cajas flexibles (display: flex). Prueba esto:

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

Las cajas flexibles me dan el control que deseé que css tuviera durante 15 años. ¡Finalmente está aquí! Más información: https://css-tricks.com/snippets/css/a-guide-to-flexbox/

BT
fuente
No sé lo que descubrió, pero su código no funciona en el último Chrome jsfiddle.net/fjb548kw/3
Yevgeniy Afanasyev
@YevgeniyAfanasyev Eliminé el "flotador: izquierda"; para solucionar el problema Gracias por la nota!
BT
Gracias. ¿Puedes explicar por qué tienes en flex-grow: 100;lugar de flex-grow: 1;?
Yevgeniy Afanasyev
2
@YevgeniyAfanasyev No hay una razón en particular, excepto que así es como me gusta hacerlo. Me permite pensar en porcentajes, así que si pudiera hacer algo como establecer #a en flex-grow:10y luego establecer #b para flex-grow: 90que #a sería el 10% del ancho de la línea y #b sería el 90% del ancho de la línea. Si ningún otro elemento tiene un estilo de ancho flexible, técnicamente no importa lo que pones.
BT
Esto funcionó mejor para mí, tratando de colocar una entrada y un botón uno al lado del otro como si fueran uno.
Souleste
29

Solución Flexbox

Para eso es la flex-growpropiedad.

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: Agregue prefijos de proveedores flexibles si así lo requieren sus navegadores compatibles .

Reggie Pinkham
fuente
27

Este sería un buen ejemplo de algo que es trivial hacer con tablas y difícil (si no imposible, al menos en un sentido de navegador cruzado) de CSS.

Si ambas columnas fueran de ancho fijo, esto sería fácil.

Si una de las columnas tuviera un ancho fijo, esto sería un poco más difícil pero completamente factible.

Con el ancho variable de ambas columnas, en mi humilde opinión, solo necesita usar una tabla de dos columnas.

cletus
fuente
11
Sin embargo, la tabla no será muy buena en un diseño receptivo donde desea que la columna de la derecha se deslice debajo de la izquierda en dispositivos pequeños.
S ..
1
Hay algunos trucos de diseño receptivo para trabajar con tablas: css-tricks.com/responsive-data-tables
Rikki
Ahora tiendo a diseñar dos diseños completamente diferentes por completo y cambiar en un móvil usando consultas de medios y, display:none;mientras hago el máximo posible de respuesta al 100% en una escala móvil, a veces es mejor cambiar su diseño por completo para un dispositivo móvil haciendo uso de la sensación de la pantalla táctil y estilo de botones.
Bysander
22

Mira esta solución

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

angel.dimitrov
fuente
2
Generalmente, esta es una solución superior porque no siempre se desea ocultar el desbordamiento.
Joseph Lennox
3
Por OP: "Quiero un diseño div de dos columnas, donde cada uno puede tener un ancho variable". En su respuesta, debe conocer el ancho de la primera columna, por lo que no es variable. También puede establecer anchos fijos en ambas columnas y simplemente flotarlos.
Jacob Alvarez
17

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

El problema con esto es que todos los anchos deben definirse explícitamente, ya sea como un valor (px y em funcionan bien) o como un porcentaje de algo definido explícitamente.

joel Moses
fuente
15

Aquí, esto podría ayudar ...

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

a6hi5h3k
fuente
+1 porque su ejemplo parece funcionar, pero en mi escenario real, de alguna manera, los contenidos de 'vista' se arrastran hacia el 'árbol' div, ya que el árbol div no es 100%, es posible que algunos JavaScript lo obliguen a ser pequeño y después de la altura del árbol Veo ver contenido
Anurag Uniyal
En ese caso, si conoce el ancho máximo de la columna izquierda, puede darle un estilo de ancho máximo (no funciona en IE) o pensar en margen izquierdo (tenga cuidado con el error de doble margen en IE) o acolchado a la izquierda.
a6hi5h3k
Esto fue genial! Lo estoy usando en línea como una solución única:<div class="clear" style="clear: both; height: 1px; overflow: hidden; font-size:0pt; margin-top: -1px;"></div>
ajwest
5

No entiendo por qué las personas están dispuestas a trabajar tan duro para encontrar una solución de CSS puro para diseños de columnas simples que sean tan FÁCILES utilizando la TABLEetiqueta anterior.

Todos los navegadores todavía tienen la lógica de diseño de la tabla ... Llámame un dinosaurio tal vez, pero digo que te ayude.

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

Mucho menos arriesgado en términos de compatibilidad entre navegadores también.

PatM
fuente
2
sí, pero si todo se está haciendo por css, ¿por qué no esto, al menos una curiosidad si es posible?
Anurag Uniyal
2
Esto se debe a que si desea media-queriescolocar ambas columnas una encima de la otra en dispositivos pequeños, es imposible con la tableetiqueta anterior. Para que esto funcione, debe aplicar CSSestilos de tabla. Por lo tanto, hoy en día es mejor resolver esto CSSsi desea un diseño receptivo para cualquier tamaño de pantalla.
ElChiniNet
5

Si el ancho de la otra columna es fijo, ¿qué tal si la calcfunción CSS funciona para todos los navegadores comunes ?

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

De esta forma, se calculará el ancho de la segunda fila (es decir, el ancho restante) y se aplicará de manera receptiva.

anit
fuente
Esta es la mejor respuesta por lo que el uso de cualquier otra cosa que FlexBox, como por ejemplo, css-grid. También funciona con lo position: fixedque hace que sea una elección perfecta. ¡Gracias!
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>

A.Pramod Kumar
fuente
Quiero algo como una barra de estado con elementos fijos a la izquierda, elementos fijos a la derecha y una línea de mensaje que usa todo el espacio restante. Comencé con esta respuesta y agregué mi mensaje div DESPUÉS de las carrozas con: height: 20px; espacio en blanco: nowrap; desbordamiento: oculto; desbordamiento de texto: clip
englebart
3

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

canon
fuente
2

flex-grow: define la capacidad de un elemento flexible de crecer si es necesario. Acepta un valor sin unidades que sirve como proporción. Dicta qué cantidad de espacio disponible dentro del contenedor flexible debe ocupar el artículo.

Si todos los artículos tienen un sistema de crecimiento flexible en 1, el espacio restante en el contenedor se distribuirá por igual a todos los niños. Si uno de los niños tiene un valor de 2, el espacio restante ocuparía el doble de espacio que los demás (o al menos lo intentará). Ver más aquí

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

Stanislav Ostapenko
fuente
1

Una implementación ligeramente diferente,

Dos paneles div (contenido + extra), uno al lado del otro, se content panelexpanden si extra panelno está presente.

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

Rao
fuente
1

Pat - Tienes razón. Es por eso que esta solución satisfaría tanto a los "dinosaurios" como a los contemporáneos. :)

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

johnmanoahs
fuente
2
No hay referencia html para la clase css .ip y no funciona en IE7
Keith K
1

Puede usar la biblioteca CSS de W3 que contiene una clase llamada restque hace exactamente eso:

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

No olvides vincular la biblioteca CSS en la página header:

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

Aquí está la demostración oficial: W3 School Tryit Editor

manar
fuente
Parece que eso solo agrega "desbordamiento: oculto", lo que lo convierte en una versión peor de la respuesta ya dada
vpzomtrrfrt
0

No estoy seguro de si esta es la respuesta que espera, pero ¿por qué no establece el ancho de Tree en 'auto' y el ancho de 'View' al 100%?


fuente
3
Porque eso colocará el segundo flotador debajo del primero porque es demasiado ancho.
cletus
0

Eche un vistazo a los marcos de diseño CSS disponibles. Recomendaría Simpl o, el marco Blueprint un poco más complejo.

Si está utilizando Simpl (que implica importar solo un archivo simpl.css ), puede hacer esto:

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

, para un diseño de 50-50, o:

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

, para un 25-75.

Es así de simple.


fuente
¿Ambas columnas serán de ancho variable?
Anurag Uniyal
0

¡Gracias por el enchufe de Simpl.css!

recuerda envolver todas tus columnas de esta ColumnWrappermanera.

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

Estoy a punto de lanzar la versión 1.0 de Simpl.css, ¡así que ayúdenme a correr la voz!

Lanudo
fuente
0

Escribí una función de JavaScript que llamo desde jQuery $ (document) .ready (). Esto analizará todos los elementos secundarios del elemento primario principal y solo actualizará el elemento secundario más adecuado.

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"));
            }
        });
    });
}
bcr666
fuente
0

Esto es bastante fácil usando flexbox. Vea el fragmento a continuación. Agregué un contenedor contenedor para controlar el flujo y establecer una altura global. También se han agregado bordes para identificar los elementos. Tenga en cuenta que los divs ahora también se expanden a la altura completa, según sea necesario. Los prefijos de proveedor deben usarse para flexbox en un escenario del mundo real, ya que aún no es totalmente compatible.

Desarrollé una herramienta gratuita para comprender y diseñar diseños usando flexbox. Compruébalo aquí: 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>

Mario Vázquez
fuente
¿Leyó TODAS las respuestas anteriores antes de agregar las suyas? parece que no ...
Temani Afif
como nota al margen, no es necesario agregar stretchporque es el valor predeterminado y no es necesario hacer que el elemento secundario sea flexible, por lo que display:flexes inútil para los elementos internos
Temani Afif
Me pregunto por qué el voto negativo, sin ningún comentario. ¿No responde esta respuesta a la pregunta? ¿Por qué? Si tratar de ayudar a otros es penalizado, lo pensaré dos veces antes de mi próxima respuesta,
Mario Vázquez
1
Tienes dos comentarios después del voto negativo, ¿no es suficiente?
Temani Afif
Temari, ¿revisaste mi herramienta? ¿No crees que es útil y podría ayudar a otros? ¿Crees que no está relacionado con la pregunta? ¿Dónde está tu respuesta a esta pregunta? No puedo verlo ¿Cuál es tu papel aquí?
Mario Vázquez
-3

Si ambos anchos son de longitud variable, ¿por qué no calcula el ancho con algunas secuencias de comandos o del lado del servidor?

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

<div style="width: <=% getViewWidth() %>">View</div>
amischiefr
fuente
3
¿Cómo sabe el servidor cómo funcionará el motor de diseño del cliente?
Kev
Simple: desarrolle para el 90% de los navegadores :) IE 7+, FF3 + y Safari admiten CSS 3. También puede incluir el elemento estándar IE6 <! - [if lte IE 6]>. Por cierto, ¿qué navegador no admite style = "width:%"?
amischiefr
No sé cómo se puede hacer del lado del servidor, pero sí algunos javscript puede hacerlo, pero quiero evitar a menos css / html no puede hacerlo
Anurag Uniyal
Que no puede. Por lo tanto, si desea que ambos sean dinámicos, debe hacerlo en el script o en el lado del servidor.
amischiefr