Pregunta Mantener la relación de aspecto de un div con CSS


Quiero crear un div que pueda cambiar su ancho / alto a medida que cambia el ancho de la ventana.

¿Hay alguna regla CSS3 que permita cambiar la altura de acuerdo con el ancho, mientras mantiene su relación de aspecto?

Sé que puedo hacerlo a través de JavaScript, pero preferiría usar solo CSS.

div keeping aspect ratio according to width of window


796
2017-09-29 23:11


origen


Respuestas:


Solo crea un contenedor <div> con un valor porcentual para padding-bottom, Me gusta esto:

div {
  width: 100%;
  padding-bottom: 75%;
  background: gold; /** <-- For the demo **/
}
<div></div>

Dará como resultado un <div> con una altura igual al 75% del ancho de su contenedor (una relación de aspecto de 4: 3).

Esto se basa en el hecho de que para el relleno:

El porcentaje se calcula con respecto a anchura del bloque que contiene la caja generada [...] (fuente: w3.org, énfasis mío)

Valores de fondo acolchado para otras relaciones de aspecto y ancho del 100%:

aspect ratio  | padding-bottom value
--------------|----------------------
    16:9      |       56.25%
    4:3       |       75%
    3:2       |       66.66%
    8:5       |       62.5%

Colocando contenido en el div:

Para mantener la relación de aspecto del div y evitar que su contenido lo estire, debe agregar un niño completamente posicionado y estirarlo a los bordes del contenedor con:

div.stretchy-wrapper {
  position: relative;
}

div.stretchy-wrapper > div {
  position: absolute;
  top: 0; bottom: 0; left: 0; right: 0;
}

Aquí está un manifestación y otro más en profundidad manifestación


1077
2018-05-04 01:19



vw unidades:

Puedes usar vw unidades para ambos anchura y altura del elemento. Esto permite conservar la relación de aspecto del elemento, en función del ancho de la ventana gráfica.

vw: 1/100 del ancho de la ventana gráfica. [MDN]

Alternativamente, también puedes usar vh para la altura de la vista, o incluso vmin/vmax para usar las dimensiones de ventana gráfica menor o mayor (discusión aquí)

Ejemplo: relación de aspecto 1: 1

div {
  width: 20vw;
  height: 20vw;
  background: gold;
}
<div></div>

Para otras relaciones de aspecto, puede usar la siguiente tabla para calcular el valor de altura de acuerdo con el ancho del elemento:

aspect ratio  |  multiply width by
-----------------------------------
     1:1      |         1
     1:3      |         3
     4:3      |        0.75
    16:9      |       0.5625

Ejemplo: cuadrícula 4x4 de div cuadrados

body {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}
div {
  width: 23vw;
  height: 23vw;
  margin: 0.5vw auto;
  background: gold;
}
<div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div>

Aquí hay un Juega con esta demo y aquí hay una solución para hacer un cuadrícula de cuadrados receptiva con contenido centrado vertical y horizontalmente.


El soporte del navegador para unidades vh / vw es IE9 + ver canIuse para más información


327
2018-05-15 08:48



He encontrado una forma de hacer esto usando CSS, pero debes tener cuidado ya que puede cambiar dependiendo del flujo de tu propio sitio web. Lo hice para incrustar video con una relación de aspecto constante dentro de una porción de ancho fluido de mi sitio web.

Digamos que tienes un video incrustado como este:

<object>
     <param ... /><param ... />...
     <embed src="..." ...</embed>
</object>

A continuación, puede colocar todo esto dentro de un div con una clase de "video". Esta clase de video probablemente será el elemento fluido en su sitio web de tal manera que, por sí mismo, no tenga restricciones de altura directa, pero cuando cambie el tamaño del navegador, cambiará de ancho de acuerdo con el flujo del sitio web. Este sería el elemento con el que probablemente intentará obtener su video incrustado mientras mantiene cierta relación de aspecto del video.

Para hacer esto, puse una imagen antes del objeto incrustado dentro del div de la clase "video".

!!! La parte importante es que la imagen tiene la relación de aspecto correcta que desea mantener. Además, asegúrate de que el tamaño de la imagen sea AL MENOS tan grande como el más pequeño que esperas que obtenga el video (o lo que sea que mantengas el A.R.) de acuerdo con tu diseño. Esto evitará cualquier posible problema en la resolución de la imagen cuando se cambia el tamaño porcentual. Por ejemplo, si desea mantener una relación de aspecto de 3: 2, no utilice una imagen de 3px por 2px. Puede funcionar en algunas circunstancias, pero no lo he probado, y probablemente sería una buena idea evitarlo.

Probablemente ya deberías tener un ancho mínimo como este definido para elementos fluidos de tu sitio web. De lo contrario, es una buena idea hacerlo para evitar cortar elementos o superponerse cuando la ventana del navegador sea demasiado pequeña. Es mejor tener una barra de desplazamiento en algún punto. El ancho más pequeño que debe obtener una página web es alrededor de ~ 600px (incluidas las columnas de ancho fijo) porque las resoluciones de pantalla no son menores a menos que se trate de sitios compatibles con teléfonos. !!!

Utilizo un png completamente transparente, pero realmente no creo que termine importando si lo haces bien. Me gusta esto:

<div class="video">
     <img class="maintainaspectratio" src="maintainaspectratio.png" />
     <object>
          <param ... /><param ... />...
          <embed src="..." ...</embed>
     </object>
</div>

Ahora debería poder agregar CSS similar a lo siguiente:

div.video { ...; position: relative; }
div.video img.maintainaspectratio { width: 100%; }
div.video object { position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; }
div.video embed {width: 100%; height: 100%; }

Asegúrese de eliminar también cualquier declaración explícita de altura o ancho dentro del objeto e incrustar etiquetas que generalmente vienen con código de inserción / copia insertado.

La forma en que funciona depende de las propiedades de posición del elemento de clase de video y el elemento que desea mantener una determinada relación de aspecto. Aprovecha la forma en que una imagen mantendrá su relación de aspecto adecuada cuando se redimensiona en un elemento. Indica todo lo que está en el elemento de la clase de video para aprovechar al máximo la propiedad inmobiliaria proporcionada por la imagen dinámica al forzar su ancho / alto al 100% del elemento de la clase de video que se ajusta mediante la imagen.

Genial, ¿eh?

Puede que tenga que jugar un poco para que funcione con su propio diseño, pero en realidad funciona sorprendentemente bien para mí. El concepto general está ahí.


25
2017-12-22 02:08



Para agregar a la respuesta de Web_Designer, <div> tendrá una altura (compuesta enteramente por relleno inferior) del 75% del ancho de su elemento que contiene. Aquí hay un buen resumen: http://mattsnider.com/css-using-percent-for-margin-and-padding/. No estoy seguro de por qué esto debería ser así, pero así es como es.

Si desea que su div tenga un ancho distinto al 100%, necesita otro div de envoltura para establecer el ancho:

div.ar-outer{
    width: 60%; /* container; whatever width you want */
    margin: 0 auto; /* centered if you like */
}
div.ar {
    width:100%; /* 100% of width of container */
    padding-bottom: 75%; /* 75% of width of container */
    position:relative;
}
div.ar-inner {
    position: absolute;
    top: 0; bottom: 0; left: 0; right: 0;
}

Utilicé algo similar al truco de imágenes de Elliot recientemente para permitirme usar las consultas de medios de CSS para servir un archivo de logotipo diferente dependiendo de la resolución del dispositivo, pero aún así escalar proporcionalmente como <img> lo haría naturalmente (configuré el logotipo como imagen de fondo en un .png transparente con la relación de aspecto correcta). Pero la solución de Web_Designer me ahorraría una solicitud http.


13
2018-05-06 17:35



Elliot me inspiró a esta solución, gracias:

aspectratio.png es un archivo PNG completamente transparente con el tamaño de su relación de aspecto preferida, en mi caso 30x10 píxeles.

HTML

<div class="eyecatcher">
  <img src="/img/aspectratio.png"/>
</div>

CSS3

.eyecatcher img {
  width: 100%;
  background-repeat: no-repeat;
  background-size: 100% 100%;
  background-image: url(../img/autoresized-picture.jpg);
}

Tenga en cuenta:  background-size es una característica de css3 que podría no funcionar con tus navegadores de destino. Puede verificar la interoperabilidad (por ejemplo, caniuse.com)


13
2017-07-07 14:25



Como se indica en aquí en w3schools.com y algo reiterado en este respuesta aceptada, valores de relleno como porcentajes (énfasis mío):

Especifica el relleno en porcentaje del ancho del elemento que contiene

Ergo, un ejemplo correcto de un DIV receptivo que mantiene una relación de aspecto de 16: 9 es el siguiente:

CSS

.parent {
    position: relative;
    width: 100%;
}
.child {
    position: relative;
    padding-bottom: calc(100% * 9 / 16);
}
.child > div {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
}

HTML

<div class="parent">
    <div class="child">
        <div>Aspect is kept when resizing</div>
    </div>
</div>

Demostración en JSFiddle


9
2018-03-22 12:18



Basándome en tus soluciones, hice un truco:

Cuando lo usas, tu HTML será solo

<div data-keep-ratio="75%">
    <div>Main content</div>
</div>

Para usarlo de esta manera, haga: CSS:

*[data-keep-ratio] {
    display: block;
    width: 100%;
    position: relative;
}
*[data-keep-ratio] > * {
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
}

y js (jQuery)

$('*[data-keep-ratio]').each(function(){ 
    var ratio = $(this).data('keep-ratio');
    $(this).css('padding-bottom', ratio);
});

Y teniendo esto, acaba de configurar attr data-keep-ratio a alto / ancho y eso es todo.


9
2017-12-05 21:13



Puedes usar un svg. Haga que la posición del contenedor / envoltura sea relativa, coloque el svg primero como posición estática y luego coloque el contenido absolutamente posicionado (arriba: 0; left: 0; right: 0; bottom: 0;)

Ejemplo con proporciones de 16: 9:

image.svg: (puede ser inline en src)

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 9" width="16" height="9"/>

CSS:

.container {
  position: relative;
}
.content {
  position: absolute;
  top:0; left:0; right:0; bottom:0;
}

HTML:

<div class="container">
  <img style="width: 100%" src="image.svg" />
  <div class="content"></div>
</div>

Tenga en cuenta que svg en línea no parece funcionar, pero puede urlencode svg e incrustarlo en el atributo img src de esta manera:

<img src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2016%209%22%20width%3D%2216%22%20height%3D%229%22%2F%3E" style="width: 100%;" />

6
2017-10-05 05:26



Como @ web-tiki ya muestra una forma de usar vh/vw, También necesito una forma de centrarme en la pantalla, aquí hay un código de fragmento para 9:16 retrato.

.container {
  width: 100vw;
  height: calc(100vw * 16 / 9);
  transform: translateY(calc((100vw * 16 / 9 - 100vh) / -2));
}

translateY mantendrá este centro en la pantalla. calc(100vw * 16 / 9) se espera altura para 9/16.(100vw * 16 / 9 - 100vh) es la altura del desbordamiento, por lo tanto, tire hacia arriba overflow height/2 lo mantendrá centrado en la pantalla.

Para el paisaje, y mantener 16: 9, muestras el uso

.container {
  width: 100vw;
  height: calc(100vw * 9 / 16);
  transform: translateY(calc((100vw * 9 / 16 - 100vh) / -2));
}

La relación 9/16 es fácil de cambiar, no es necesario predefinir 100:56.25 o 100:75.Si desea asegurar primero la altura, debe cambiar el ancho y el alto, p. height:100vh;width: calc(100vh * 9 / 16) para 9:16 retrato.

Si desea adaptarse para diferentes tamaños de pantalla, también puede interesarle

  • tamaño de fondo cubrir / contener
    • El estilo anterior es similar a contener, depende de la relación ancho: altura.
  • ajuste de objeto
    • cubrir / contener para etiqueta img / video
  • @media (orientation: portrait)/@media (orientation: landscape)
    • Consulta de medios para portrait/landscape para cambiar la relación

4
2017-11-01 02:40



SCSS es la mejor solución en mi caso; usando un atributo de datos:

[data-aspect-ratio] {
    display: block;
    max-width: 100%;
    position: relative;

    &:before {
        content: '';
        display: block;
    }

    > * {
        display: block;
        height: 100%;
        left: 0;
        position: absolute;
        top: 0;
        width: 100%;
    }
}
[data-aspect-ratio="3:1"]:before {
    padding-top: 33.33%;
}
[data-aspect-ratio="2:1"]:before {
    padding-top: 50%;
}
[data-aspect-ratio="16:9"]:before {
    padding-top: 56.25%;
}
[data-aspect-ratio="3:2"]:before {
    padding-top: 66.66%;
}
[data-aspect-ratio="4:3"]:before {
    padding-top: 75%;
}
[data-aspect-ratio="1:1"]:before {
    padding-top: 100%;
}
[data-aspect-ratio="3:4"]:before {
    padding-top: 133.33%;
}
[data-aspect-ratio="2:3"]:before {
    padding-top: 150%;
}
[data-aspect-ratio="9:16"]:before {
    padding-top: 177.77%;
}
[data-aspect-ratio="1:2"]:before {
    padding-top: 200%;
}
[data-aspect-ratio="1:3"]:before {
    padding-top: 300%;
}

Por ejemplo :

<div data-aspect-ratio="16:9"><iframe ...></iframe></div>

fuente


3
2017-10-23 11:18



Solo una idea o un truco.

div {
  background-color: blue;
  width: 10%;
  transition: background-color 0.5s, width 0.5s;
  font-size: 0;
}

div:hover {
  width: 20%;
  background-color: red;
}
  
img {
  width: 100%;
  height: auto;
  visibility: hidden;
}
<div>
  <!-- use an image with target aspect ratio. sample is a square -->
  <img src="http://i.imgur.com/9OPnZNk.png" />
</div>


2
2017-09-30 15:43