Ancho de división 100% menos cantidad fija de píxeles

316

¿Cómo puedo lograr la siguiente estructura sin usar tablas o JavaScript? Los bordes blancos representan los bordes de los divs y no son relevantes para la pregunta.

Estructura 1

El tamaño del área en el medio variará, pero tendrá valores de píxeles exactos y toda la estructura debería escalar de acuerdo con esos valores. Para simplificarlo, necesitaría una forma de establecer el ancho "100% - n px" en los divs superior-medio e inferior-medio.

Agradecería una solución limpia para varios navegadores, pero en caso de que no sea posible, los hacks CSS funcionarán.

Aquí hay un bono. Otra estructura con la que he estado luchando y termina usando tablas o JavaScript. Es ligeramente diferente, pero presenta nuevos problemas. Lo he estado utilizando principalmente en un sistema de ventanas basado en jQuery, pero me gustaría mantener el diseño fuera del script y solo controlar el tamaño de un elemento (el del medio).

Estructura 2

Cuenta_Eliminada
fuente
Para el segundo elemento, está diciendo que desea que se fije la altura del elemento intermedio, pero que los otros elementos cercanos sean dinámicos
Casebash

Respuestas:

78

Puede usar elementos anidados y relleno para obtener un borde izquierdo y derecho en la barra de herramientas. El ancho predeterminado de un divelemento es auto, lo que significa que usa el ancho disponible. Luego puede agregar relleno al elemento y aún se mantiene dentro del ancho disponible.

Aquí hay un ejemplo que puede usar para colocar imágenes como esquinas redondeadas izquierda y derecha, y una imagen central que se repite entre ellas.

El HTML:

<div class="Header">
   <div>
      <div>This is the dynamic center area</div>
   </div>
</div>

El CSS:

.Header {
   background: url(left.gif) no-repeat;
   padding-left: 30px;
}
.Header div {
   background: url(right.gif) top right no-repeat;
   padding-right: 30px;
}
.Header div div {
   background: url(center.gif) repeat-x;
   padding: 0;
   height: 30px;
}
Guffa
fuente
Gracias por eso. Tuve que modificarlo un poco para mi situación. El primer div anidado necesitaba un margen derecho en lugar de relleno, y el div central también necesitaba el mismo margen derecho.
Max
3
Gran solución solo una pequeña cosa -> esto funciona porque ".Header div div" anula ".Header div" . Debería ser ".Header> div" y ".Header> div> div" en su lugar. De hecho, ".Header div" significa cualquier niño div o sub div niño mientras que ".Header> div" significa solo hijos directos de .Header
Charles HETIER
@CharlesHETIER: Sí, eso también funciona y es más fácil de usar, ya que no tiene que anular todas las configuraciones de la regla menos específica. La respuesta se escribió cuando el soporte para el >operador todavía no era lo suficientemente bueno como para ser confiable.
Guffa
1
Esto está desactualizado, vea la respuesta a continuación sobre la función calc en css.
María Arias de Reyna Domínguez
2
@delawen: Tienes que esperar un poco antes de que quede desactualizado. No hay soporte para calcIE 8, o las versiones actuales de Anroid Browser u Opera. caniuse.com/#search=calc
Guffa
760

Nueva forma en la que me he topado: csscalc() :

.calculated-width {
    width: -webkit-calc(100% - 100px);
    width:    -moz-calc(100% - 100px);
    width:         calc(100% - 100px);
}​

Fuente: css ancho 100% menos 100px

rom_j
fuente
86
La mejor respuesta en 2013 en mi humilde opinión. La respuesta aceptada está desactualizada.
Danubian Sailor
77
Ya es hora de que alguien tropiece con esto. He terminado con los hacks ahora que sé esto. +1 @lechlukasz
preahkumpii
47
¡Después de 10 años de CSS luchando, esta respuesta merece +20000! Todavía no puedo creer lo que veo ...
skobaljic
8
Todo lo que puedo decir es ... youtube.com/…
Jazz
55
¿Más compatible? -> $ ('# yourEl'). css ('ancho', '100%'). css ('ancho', '- = 100px'); (jQuery)
sboy031 18/0913
7

Si bien la respuesta de Guffa funciona en muchas situaciones, en algunos casos es posible que no desee que los pedazos de relleno izquierdo y / o derecho sean los padres del div central. En estos casos, puede usar un contexto de formato de bloque en el centro y flotar los divisores de relleno a izquierda y derecha. Aquí está el código

El HTML:

<div class="container">
    <div class="left"></div>
    <div class="right"></div>
    <div class="center"></div>
</div>

El CSS:

.container {
    width: 100px;
    height: 20px;
}

.left, .right {
    width: 20px;
    height: 100%;
    float: left;
    background: black;   
}

.right {
    float: right;
}

.center {
    overflow: auto;
    height: 100%;
    background: blue;
}

Siento que esta jerarquía de elementos es más natural en comparación con los div anidados anidados, y representa mejor lo que hay en la página. Debido a esto, los bordes, el relleno y el margen se pueden aplicar normalmente a todos los elementos (es decir: esta 'naturalidad' va más allá del estilo y tiene ramificaciones).

Tenga en cuenta que esto solo funciona en divs y otros elementos que comparten su propiedad 'llenar el 100% del ancho por defecto'. Las entradas, tablas y posiblemente otros requerirán que los envuelva en un contenedor div y agregue un poco más de CSS para restaurar esta calidad. Si tienes la mala suerte de estar en esa situación, contáctame y desenterraré el CSS.

jsfiddle aquí: jsfiddle.net/RgdeQ

¡Disfrutar!

Unislash
fuente
6

Puede hacer uso del diseño de Flexbox . Debe establecer flex: 1el elemento que debe tener ancho o alto dinámico para flex-direction: row and columnrespectivamente.

Ancho dinámico:

HTML

<div class="container">
  <div class="fixed-width">
    1
  </div>
  <div class="flexible-width">
    2
  </div>
  <div class="fixed-width">
    3
  </div>
</div>

CSS

.container {
  display: flex;
}
.fixed-width {
  width: 200px; /* Fixed width or flex-basis: 200px */
}
.flexible-width {
  flex: 1; /* Stretch to occupy remaining width i.e. flex-grow: 1 and flex-shrink: 1*/
}

Salida:


Altura dinámica:

HTML

<div class="container">
  <div class="fixed-height">
    1
  </div>
  <div class="flexible-height">
    2
  </div>
  <div class="fixed-height">
    3
  </div>
</div>

CSS

.container {
  display: flex;
}
.fixed-height {
  height: 200px; /* Fixed height or flex-basis: 200px */
}
.flexible-height {
  flex: 1; /* Stretch to occupy remaining height i.e. flex-grow: 1 and flex-shrink: 1*/
}

Salida:

Manoj Kumar
fuente
3

La forma habitual de hacerlo es como lo describe Guffa, elementos anidados. Es un poco triste tener que agregar un marcado adicional para obtener los ganchos que necesita para esto, pero en la práctica, un divisor de envoltura aquí o allá no le hará daño a nadie.

Si debe hacerlo sin elementos adicionales (por ejemplo, cuando no tiene control del marcado de la página), puede usar el tamaño de cuadro , que tiene un soporte de navegador bastante decente pero no completo o simple. Sin embargo, es probable que sea más divertido que tener que confiar en las secuencias de comandos.

bobince
fuente
3

Tal vez estoy siendo tonto, pero ¿no es la mesa la solución obvia aquí?

<div class="parent">
    <div class="fixed">
    <div class="stretchToFit">
</div>

.parent{ display: table; width 100%; }
.fixed { display: table-cell; width: 150px; }
.stretchToFit{ display: table-cell; vertical-align: top}

Otra forma que he descubierto en Chrome es aún más simple, ¡pero hombre, es un truco!

.fixed{ 
   float: left
}
.stretchToFit{
   display: table-cell;
   width: 1%;
}

Esto solo debería llenar el resto de la línea horizontalmente, como lo hacen las celdas de la tabla. Sin embargo, tiene algunos problemas extraños con el hecho de que supera el 100% de su padre, sin embargo, establecer el ancho en un valor porcentual lo corrige.

Jack Franzen
fuente
2

Podemos lograr esto usando flex-box muy fácilmente.

Si tenemos tres elementos como Encabezado, Contenedor medio y Pie de página. Y queremos darle una altura fija al Encabezado y al Pie de página. entonces podemos escribir así:

Para React / RN (los valores predeterminados son 'display' como flex y 'flexDirection' como columna), en web css tendremos que especificar el contenedor del cuerpo o el contenedor que contiene estos como display: 'flex', flex-direction: 'column' como abajo:

    container-containing-these-elements: {
     display: flex,
     flex-direction: column
    }
    header: {
     height: 40,
    },
    middle-container: {
     flex: 1, // this will take the rest of the space available.
    },
    footer: {
     height: 100,
    }
jayiitb
fuente
1

qué sucede si su div de envoltura era 100% y usó relleno para una cantidad de píxeles, entonces si el # de relleno necesita ser dinámico, puede usar fácilmente jQuery para modificar la cantidad de relleno cuando se disparan sus eventos.

dfasdljkhfaskldjhfasklhf
fuente
1

Tuve un problema similar en el que quería un banner en la parte superior de la pantalla que tuviera una imagen a la izquierda y una imagen repetida a la derecha en el borde de la pantalla. Terminé resolviéndolo así:

CSS:

.banner_left {
position: absolute;
top: 0px;
left: 0px;
width: 131px;
height: 150px;
background-image: url("left_image.jpg");
background-repeat: no-repeat;
}

.banner_right {
position: absolute;
top: 0px;
left: 131px;
right: 0px;
height: 150px;
background-image: url("right_repeating_image.jpg");
background-repeat: repeat-x;
background-position: top left;
}

La clave era la etiqueta correcta. Básicamente estoy especificando que quiero que se repita desde 131px desde la izquierda hasta 0px desde la derecha.

Mike Carey
fuente
0

En algunos contextos, puede aprovechar la configuración de margen para especificar efectivamente "100% de ancho menos N píxeles". Vea la respuesta aceptada a esta pregunta .

caos
fuente