Contenedores de ancho completo en padres de ancho limitado | Programar Plus

Yo marcaba un tweet hace unos meses, ya que era un truco CSS auténtico y eso es lo que nos encanta por aquí.

El problema es: ¿Cómo hacemos un contenedor de ancho de navegador completo cuando estamos dentro de un padre de ancho limitado?

Punto de partida

Esta imagen es 100% ancha ya que es un elemento primario de ancho limitado.

Queremos estirarlo exactamente tanto como la ventana del navegador.

Aquí hay un margen mínimo asumido:

<!-- parent -->
<main>

  <p>Stuff.</p>

  <!-- container we want to be full width -->
  <figure class="full-width">
    <!-- could be whatever content -->
    <img src="https://css-tricks.com/full-width-containers-limited-width-parents/dog.jpg" alt="">
  </figure>

</main>

Consideraciones

Si pudiéramos usar el posicionamiento absoluto, podríamos configurar el contenedor para que esté en left: 0; y width: 100%; – pero no podemos, porque queremos que el contenedor permanezca en flujo.

¿No podemos simplemente aplicar un margen negativo a cada lado y tirar de él hacia afuera? ¡En algunas circunstancias, podemos!

Con% conocido de ancho

Digamos que el contenedor principal tenía un 60% de ancho y estaba centrado. Eso significa que hay un 20% de ancho a cada lado. Pero el margen se calcula en función del elemento principal, por lo que para tirarlo hacia la izquierda el 20% de la ventana del navegador, necesitaría 1/3 del ancho del elemento principal, así que …

main {
  width: 60%;
  margin: 0 auto;
  /* creates 20% margins on either side */
}
.full-width {
  /* 1/3 of 60% = the 20% margin on either side */
  margin-left: -33.33%;
  margin-right: -33.33%;
}

Con ancho de padre no% conocido

En la mayoría de las demás circunstancias, simplemente no tenemos suficiente información para saber exactamente hasta dónde sacar el contenedor de ancho completo con márgenes negativos.

Bueno, a menos que …

Podríamos usar el ancho de la ventana del navegador en nuestra matemática CSS. La cantidad que queremos “tirar” hacia la izquierda y la derecha es la mitad del ancho de la ventana del navegador más la mitad del ancho del padre. (Suponiendo que el padre está centrado).

Entonces, nuestro padre tiene 500px de ancho:

.full-width {
  margin-left: calc(-100vw / 2 + 500px / 2);
  margin-right: calc(-100vw / 2 + 500px / 2);
}

Un ancho fijo como ese se siente un poco rojo (es decir, ¿qué sucede en pantallas más estrechas?), Todo esto probablemente estaría envuelto en una consulta de medios que hace que solo se aplique en pantallas más grandes:

@media (min-width: 500px) {
  main {
    width: 500px;
    margin: 0 auto;
  }
  .full-width {
    margin-left: calc(-100vw / 2 + 500px / 2);
    margin-right: calc(-100vw / 2 + 500px / 2);
  }
}

Dado que nuestra demostración era una imagen, también puede hacer algo como .full-width img { width: 100%; } también, para obtener esa cobertura completa.

Si se trata menos de flexión del cerebro, es posible que tenga suerte reduciendo a:

@media (min-width: $max-width) {
  .full-width {
    margin-left: calc(50% - 50vw);
    margin-right: calc(50% - 50vw);
  }
}

Traducir

Dado que las animaciones (probablemente) no están involucradas aquí, probablemente no sea muy necesario, pero podría llevar el contenedor al borde con transformaciones en su lugar.

@media (min-width: 40em) {
  .full-width {
    width: 100vw;
    transform: translateX(calc((40em - 100vw)/2));
  }
}

@supports ()

La idea anterior fue tomada de un Pen por Brandon Mathis donde combinó esa idea con envolverlo todo en @supports.

/* See warning below */
@supports (width: 100vw) {
  .full-width {
    width: 100vw;
  }
  @media all and (min-width: 40rem) {
    .full-width {
       transform: translateX(calc((40rem - 100vw)/2));
    }
  }
}

La idea aquí es que nada de esto se aplicaría si el navegador no fuera compatible con las unidades de visualización. De esa manera, podría tirar del comportamiento de respaldo por encima de este en el CSS y dejar que esto lo anule si puede.

Parece una buena idea, pero en mis pruebas solo Firefox acertó. Chrome a veces aplicaba incorrectamente la consulta de medios cuando no se suponía que debía hacerlo (captura de pantalla). (Digo “a veces” porque parecía que un nuevo dibujo lo “arreglaría”, solo para no aplicar la consulta de medios en la otra dirección). Edge tampoco parecía aplicar las reglas de consulta de medios en absoluto (captura de pantalla). Quizás las @-reglas anidadas todavía tienen algunos errores.

No se necesita calc ()

Sven Wolfermann siguió la idea de Jon Neal con una variación inteligente que no necesita calc ():

.full-width {
  width: 100vw;
  position: relative;
  left: 50%;
  right: 50%;
  margin-left: -50vw;
  margin-right: -50vw;
}

La idea aquí es: empujar el contenedor al centro exacto de la ventana del navegador con left: 50%;, luego tire de él hacia el borde izquierdo con negativo -50vw margen.

¡Muy inteligente! De esta manera, no necesita ninguna información sobre el ancho principal. Tenga en cuenta que tanto esto como el calc() La versión requiere que el padre esté exactamente centrado en el navegador.

Incluso podrías pensar: ¿por qué molestarse con el right y margin-right? Es cierto que no lo necesita en un sitio de izquierda a derecha, pero si existe alguna posibilidad de direction: rtl; Sucede, necesitará las propiedades correctas, por lo que tener ambas es más a prueba de balas.

Voy a poner una bifurcación de este método aquí, ya que parece el más útil.

Vea la imagen del ancho de la ventana gráfica completa de Pen (contenedor) dentro del artículo de Chris Coyier (@chriscoyier) en CodePen.