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


1059

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

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

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

relación de aspecto de mantenimiento de div según el ancho de la ventana


3
Escribí sobre diferentes enfoques para esto en mi artículo de CSS-Tricks sobre cómo escalar animaciones receptivas
Zach Saucier el

2
Llegué a estas preguntas y respuestas muy tarde, pero debo comentar. Aunque es muy disciplinado y dentro de las reglas SO de todos los que responden para hacer todo lo posible para satisfacer la demanda "única CSS" de la pregunta, es bastante sorprendente que con la excepción de la respuesta del usuario 007 en la parte inferior de la página, no- uno ha mencionado lo obvio: no existe una solución confiable de solo CSS, este problema requiere Javascript. Un novato que ingrese a esta página podría perder un tiempo valioso al cambiar de un conjunto de pros / contras a otro antes de que se apague la bombilla: solo CSS no funcionará.
Theo d'Or el

1
Escribí una pequeña herramienta que facilita la vista previa y el cálculo de las relaciones de aspecto, aspectorat.io . También genera el código CSS / Sass / Less apropiado que puede copiar y pegar en sus proyectos. Espero que la gente lo encuentre útil.
Ryan Hefner

mira este ejemplo: w3schools.com/howto/howto_css_aspect_ratio.asp ..... eso me funcionó
Cristian Agudelo

1
Esta pregunta es para establecer la altura en función del ancho . Si necesita lo contrario, consulte Configuración del ancho del elemento en función de la altura mediante CSS .
John Mellor

Respuestas:


1354

Simplemente cree un contenedor <div>con un valor de porcentaje para padding-bottom, como este:

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

/* demonstration purposed only : non-essential */
.demoWrapper {
  padding: 10px;
  background: white;
  box-sizing: border-box;
  resize: horizontal;
  border: 1px dashed;
  overflow: auto;
  max-width: 100%;
  height: calc(100vh - 16px);
}
<div class="demoWrapper">
  <div></div>
</div>

El resultado será una <div>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 al ancho del bloque que contiene la caja generada [...] (fuente: w3.org , énfasis mío)

Valores de relleno inferior para otras relaciones de aspecto y 100% de ancho:

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

Colocar contenido en el div:

Para mantener la relación de aspecto del div y evitar que su contenido lo estire, debe agregar un elemento secundario absolutamente posicionado y estirarlo hasta los bordes del envoltorio con:

div.stretchy-wrapper {
  position: relative;
}

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

He aquí una demostración y otro más en profundidad de demostración


29
@schellmax, se debe a que el% de relleno se calcula en relación con el ancho del elemento actual, mientras que el% de altura se calcula en relación con la altura del elemento principal. Además, las posiciones absolutas se calculan en relación con el contenedor exterior de un elemento, que incluye el área de relleno. Para obtener más información, Google "CSS Box Model"
Anson Kao

11
Esto no parece funcionar de manera anidada. Funciona en el primer nivel, pero cuando se trata de hacer lo mismo dentro de la relación de aspecto de mantenimiento del div, el porcentaje de relleno inferior parece aplicarse al ancho del elemento primario. Aquí hay un ejemplo en el que .stretchy-wrap.onethird padding-bottom del 25% es en realidad el 25% del ancho principal. ¿Alguien puede explicar esto?
Misterparker

44
Completamente asombroso. Me está matando que esta técnica no funcione cuando quieres fijar la altura al 100%. @Misterparker, la técnica se basa en los cálculos de ancho y relleno que se realizan con la misma referencia; no puede usar un ancho menor al 100%, como lo ha hecho en su ejemplo.
steveluscher

2
@Misterparker Sí, el porcentaje de relleno se calcula en proporción al ancho del elemento principal. Vea el ejemplo más detallado que publiqué en una edición de mi respuesta. Mi demo actualizada muestra una 'moda anidada' de la que estabas hablando.
Web_Designer

3
El hecho de que haya demostrado que esto funciona es suficiente para convencerme de que esta es la mejor respuesta que he visto en SO. grita a mi hombre @Web_Designer

410

vw unidades:

Puede usar vwunidades tanto para el ancho como para la altura del elemento. Esto permite preservar 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 puede usar vhpara la altura de la vista, o incluso vmin/ vmaxpara usar la menor / mayor de las dimensiones de la vista (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 la 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 divisiones cuadradas

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 violín con esta demostración y aquí hay una solución para hacer una cuadrícula receptiva de cuadrados con contenido centrado vertical y horizontalmente .


La compatibilidad del navegador para las unidades vh / vw es IE9 +, consulte canIuse para obtener más información


14
Esta debería ser la respuesta aceptada. Quizás no ahora, sino en el futuro. Las unidades vw son compatibles con la mayoría de los navegadores ahora .
agosto

3
@vivekmaharajh ambas técnicas son buenas, cada una tiene sus propias ventajas y desventajas. Usar uno u otro depende en gran medida de la situación.
web-tiki

11
@ web-tiki, tienes razón. Me he encontrado con un problema: se supone que el ancho del elemento es proporcional al ancho de la ventana gráfica, que no será el caso si 1) tiene cosas como canales de ancho fijo, o 2) tiene el ancho máximo establecido para algunos de tus elementos
Vivek Maharajh

1
Tal vez sea solo Chrome v47beta, pero cuando configuro el div width:50%y height:50vwla altura es un poco más alta que el ancho, no es exactamente una proporción 1: 1. ¿Algunas ideas?
Thdoan

2
@ 10basetom es un comportamiento normal. Las unidades vw contienen el ancho de la barra de desplazamiento, mientras que% width no. La diferencia entre la altura y el ancho dependerá del tamaño de la barra de desplazamiento, que es diferente según el navegador.
web-tiki

26

He encontrado una manera de hacer esto usando CSS, pero debes tener cuidado, ya que puede cambiar dependiendo del flujo de tu propio sitio web. Lo hice para insertar videos 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í misma, no tiene restricciones de altura directas, pero cuando cambie el tamaño del navegador cambiará de ancho de acuerdo con el flujo del sitio web. Este sería el elemento en el que probablemente esté intentando obtener su video incrustado mientras mantiene una cierta relación de aspecto del video.

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

!!! La parte importante es que la imagen tiene la relación de aspecto correcta que desea mantener. Además, asegúrese de que el tamaño de la imagen sea AL MENOS tan grande como el más pequeño que espera que obtenga el video (o lo que sea que esté manteniendo el AR) según su diseño. Esto evitará posibles problemas 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 use solo una imagen de 3 px por 2 px. Puede funcionar en algunas circunstancias, pero no lo he probado, y probablemente sería una buena idea evitarlo.

Probablemente ya debería tener un ancho mínimo como este definido para elementos fluidos de su sitio web. De lo contrario, es una buena idea hacerlo para evitar cortar elementos o superponerlos cuando la ventana del navegador sea demasiado pequeña. Es mejor tener una barra de desplazamiento en algún momento. El ancho más pequeño que debe tener una página web es de alrededor de ~ 600px (incluidas las columnas de ancho fijo) porque las resoluciones de pantalla no se reducen 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 al 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 alto o ancho dentro del objeto y las etiquetas de inserción que generalmente vienen con el código de inserción copiado / pegado.

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 cierta relación de aspecto. Aprovecha la forma en que una imagen mantendrá su relación de aspecto adecuada cuando se redimensiona en un elemento. Le dice a lo que sea que esté en el elemento de la clase de video que aproveche al máximo el espacio real proporcionado por la imagen dinámica al forzar su ancho / alto al 100% del elemento de la clase de video que la imagen ajusta.

Muy bien, ¿eh?

Es posible que tengas que jugar un poco para que funcione con tu propio diseño, pero esto realmente funciona sorprendentemente bien para mí. El concepto general está ahí.


17

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 función css3 que podría no funcionar con sus navegadores de destino. Puede verificar la interoperabilidad (por ejemplo, caniuse.com ).


14

Para agregar a la respuesta de Web_Designer, <div>tendrá una altura (compuesta completamente por el relleno inferior) del 75% del ancho del elemento que lo 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 diferente al 100%, necesita otro div de envoltura en el que 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 imagen de Elliot recientemente para permitirme usar consultas de medios CSS para servir un archivo de logotipo diferente dependiendo de la resolución del dispositivo, pero aún así escalar proporcionalmente como lo <img>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.


Gran solución En mi caso, sé el tamaño de imagen "natural" cuando lo coloco en DOM y necesito tener un marcador de posición de imagen con la altura adecuada para evitar un mayor desplazamiento una vez que el navegador carga las imágenes. En .ar-outside tengo el ancho de la imagen en píxeles, en .ar tengo el relleno inferior calculado a partir de la relación de aspecto de la imagen real. En lugar de ar-inner, tengo la imagen en sí (<img>). Sin embargo, tuve que establecer el ancho al 100% en lugar de configurar la parte superior, inferior, izquierda y derecha. Cuando configuro maxWidth en ar-external, la imagen se escala muy bien cuando padre es pequeño, pero no escala a un tamaño mayor que su tamaño natural.
Mi-La

13

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

Especifica el relleno en porcentaje del ancho del elemento contenedor

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>

Demo en JSFiddle


13

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 el retrato de 9:16 .

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

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

Para el paisaje y mantener 16: 9 , muestra uso

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

La proporción de 9/16 es la facilidad para el cambio, no hay necesidad de predefinido 100:56.25o 100:75Si usted quiere asegurarse de altura en primer lugar, usted debe cambiar la anchura y la altura, por ejemplo height:100vh;width: calc(100vh * 9 / 16)para la 9:16 retrato.

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

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

11

Esta es una mejora en la respuesta aceptada:

  • Utiliza pseudo elementos en lugar de envoltorios divs
  • La relación de aspecto se basa en el ancho del cuadro en lugar de su padre
  • La caja se estirará verticalmente cuando el contenido se vuelva más alto

.box {
  margin-top: 1em;
  margin-bottom: 1em;
  background-color: #CCC;
}

.fixed-ar::before {
  content: "";
  float: left;
  width: 1px;
  margin-left: -1px;
}
.fixed-ar::after {
  content: "";
  display: table;
  clear: both;
}

.fixed-ar-16-9::before {
  padding-top: 56.25%;
}
.fixed-ar-3-2::before {
  padding-top: 66.66%;
}
.fixed-ar-4-3::before {
  padding-top: 75%;
}
.fixed-ar-1-1::before {
  padding-top: 100%;
}

.width-50 {
  display: inline-block;
  width: 50%;
}
.width-20 {
  display: inline-block;
  width: 20%;
}
<div class="box fixed-ar fixed-ar-16-9">16:9 full width</div>
<hr>
<div class="box fixed-ar fixed-ar-16-9 width-50">16:9</div>
<hr>
<div class="box fixed-ar fixed-ar-16-9 width-20">16:9</div>
<div class="box fixed-ar fixed-ar-3-2 width-20">3:2</div>
<div class="box fixed-ar fixed-ar-4-3 width-20">4:3</div>
<div class="box fixed-ar fixed-ar-1-1 width-20">1:1</div>
<hr>
<div class="box fixed-ar fixed-ar-16-9 width-20">16:9</div>
<div class="box fixed-ar fixed-ar-16-9 width-50">16:9</div>


¿Cómo deshabilitar el estiramiento vertical de la caja? estrictamente hablando, un div de estiramiento no mantiene su relación de aspecto
florian

Si el contenido es más alto que la altura esperada, la caja se estirará verticalmente. Esta idea se utiliza mejor con contenido que podría extenderse para que coincida con las dimensiones de sus padres, por ejemplo, video e imágenes.
Salman A

10

Me topé con una solución inteligente usando <svg>y display:grid.

El elemento de cuadrícula le permite ocupar el mismo espacio con dos (o más) elementos, sin necesidad de especificar cuál establece la altura. Lo que significa que, fuera de la caja, el más alto establece la relación .

Esto significa que puede usarlo tal como está cuando sabe que el contenido nunca será lo suficientemente alto como para llenar toda la "relación" y simplemente está buscando una manera de colocar el contenido en este espacio (es decir, centrarlo en ambas direcciones) display:flex; align-items:center; justify-content:center)
Es más o menos lo mismo que usar un sistema transparente <img>con display:blocky relación predeterminada, excepto el <svg>más ligero y mucho más fácil de modificar (para cambiar la relación responsablemente, si necesita).

<div class="ratio">
  <svg viewBox="0 0 1 1"></svg>
  <div>
    I'm square
  </div>
</div>
.ratio {
  display: grid;
}
.ratio > * {
  grid-area: 1/1/1/1;
}

Todo lo que necesitas hacer es cambiar la <svg>relación s:

  • <svg viewBox="0 0 4 3"></svg>
  • <svg viewBox="0 0 16 9"></svg>

Véalo trabajando:


Si necesita una solución donde el elemento de contenido no puede establecer la proporción cuando es más alto (con desbordamiento oculto o automático), debe configurarlo position:relativeen la cuadrícula y position:absolute; height:100%; overflow-y: auto;en el contenido. Ejemplo:


9

Basándome en sus soluciones, he hecho un truco:

Cuando lo use, su HTML será solo

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

Para usarlo de esta manera haz: 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, simplemente establece attr data-keep-ratioen alto / ancho y eso es todo.


3
deberías usar data-keep-rationot keep-ratioy obtener su valor usando$(this).data('keep-ratio');
Robert

su código está funcionando ahora y tal vez funcionará para siempre, pero no es estándar y los navegadores pueden dejar de admitirlo en cualquier momento en el futuro
Robert

1
¡Usar JS aquí causará malas noticias!
Amir Hossein Ahmadi

8

Puedes usar un svg. Haga que la posición del contenedor / envoltorio sea relativa, coloque el svg primero como estático y luego coloque el contenido en una posición absoluta (arriba: 0; izquierda: 0; derecha: 0; abajo: 0;)

Ejemplo con proporciones 16: 9:

image.svg: (se puede incluir 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 el 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%;" />

7

SCSS es la mejor solución en mi caso; utilizando 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


15
Solo para su información ... Puede hacer esto exactamente (usando selectores de atributos) en exactamente la misma cantidad de líneas usando CSS simple. El [data-aspect-ratio]selector de atributos está disponible para usted en CSS.
rnevius

6

Si bien la mayoría de las respuestas son muy interesantes, la mayoría de ellas requieren que la imagen ya tenga el tamaño correcto ... Otras soluciones solo funcionan para un ancho y no tienen en cuenta la altura disponible, pero a veces también desea ajustar el contenido en una altura determinada. .

Intenté unirlos para brindar una solución totalmente portátil y redimensionable ... El truco es usar la escala automática de una imagen pero usar un elemento svg en línea en lugar de usar una imagen renderizada previamente o cualquier forma de segunda solicitud HTTP ...

div.holder{
  background-color:red;
  display:inline-block;
  height:100px;
  width:400px;
}
svg, img{
  background-color:blue;
  display:block;
  height:auto;
  width:auto;
  max-width:100%;
  max-height:100%;
}
.content_sizer{
  position:relative;
  display:inline-block;
  height:100%;
}
.content{
  position:absolute;
  top:0;
  bottom:0;
  left:0;
  right:0;
  background-color:rgba(155,255,0,0.5);
}
<div class="holder">
  <div class="content_sizer">
    <svg width=10000 height=5000 />
    <div class="content">
    </div>
  </div>
</div>

Tenga en cuenta que he usado valores grandes en los atributos de ancho y alto del SVG, ya que debe ser más grande que el tamaño máximo esperado, ya que solo puede reducirse. El ejemplo hace que la relación del div 10: 5


4

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>


Esta no es una solución solo para CSS ... Ahora, si hubiera usado una imagen codificada en base64 en un pseudo elemento, esa habría sido una solución genial.
rnevius

1
Realmente no hay una solución solo para CSS. HTML es el componente básico de la web. Creo que el propósito de la pregunta es abstenerse de usar JS tal vez para ahorrar recursos / procesamiento.
orlland

No estoy seguro de si el pseudo elemento funcionará. Utilicé la propiedad de img element para mantener su relación de aspecto para que esta solución funcione.
orlland

Agradable, pero calcula una altura solo cuando cambia el ancho. Debe hacerlo en ambos sentidos, por lo que cuando reduzco la altura, el ancho también se vuelve a calcular. De lo contrario es inútil ..
Ωmega

4

supongamos que tiene 2 divs, el div externo es un contenedor y el interno podría ser cualquier elemento que necesite para mantener su relación (img o un iframe de youtube o lo que sea)

html se ve así:

<div class='container'>
  <div class='element'>
  </div><!-- end of element -->

supongamos que necesita mantener la proporción del "elemento"

relación => 4 a 1 o 2 a 1 ...

css se ve así

.container{
  position: relative;
  height: 0
  padding-bottom : 75% /* for 4 to 3 ratio */ 25% /* for 4 to 1 ratio ..*/

}

.element{
  width : 100%;
  height: 100%;
  position: absolute; 
  top : 0 ;
  bottom : 0 ;
  background : red; /* just for illustration */
}

el relleno cuando se especifica en% se calcula en función del ancho, no de la altura. .. así que básicamente no importa cuál sea su ancho, la altura siempre se calculará en función de eso. que mantendrá la proporción.


4

Me he encontrado con este problema muchas veces, así que hice una solución JS para ello. Básicamente, esto ajusta la altura del domElement según el ancho del elemento según la relación que especifique. Puede usarlo de la siguiente manera:

<div ratio="4x3"></div>

Tenga en cuenta que, dado que establece la altura del elemento, el elemento debe ser a display:blocko display:inline-block.

https://github.com/JeffreyArts/html-ratio-component


1
Aunque no he visto o probado tu código (ya tengo el mío), he votado tu respuesta solo por el hecho de que presentas la única solución confiable, un script JS.
Theo d'Or el

La pregunta pedía específicamente una solución que no necesitara Javascript.
Flimm

4

Si desea ajustar un cuadrado dentro de la ventana gráfica en vista vertical u horizontal (lo más grande posible, pero nada sobresaliendo), cambie entre usar vw/ vhen orientación portrait/ landscape:

@media (orientation:portrait ) {
  .square {
    width :100vw;
    height:100vw;
  }
} 
@media (orientation:landscape) {
  .square {
    width :100vh;
    height:100vh;
  }
} 

4

Me gustaría compartir mi solución, donde tengo una imgetiqueta que llena una determinada relación de aspecto. No podía usar backgrounddebido a la falta de apoyo de la CMS y no me prefiere usar una etiqueta de estilo de esta manera: <img style="background:url(...)" />. Además, el ancho es del 100%, por lo que no es necesario establecerlo en un tamaño fijo como en algunas de las soluciones. ¡Se escalará de manera receptiva!

.wrapper {
  width: 50%;
}

.image-container {
  position: relative;
  width: 100%;
}

.image-container::before {
  content: "";
  display: block;
}

.image-container img {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.ratio-4-3::before {
  padding-top: 75%;
}

.ratio-3-1::before {
  padding-top: calc(100% / 3);
}

.ratio-2-1::before {
  padding-top: 50%;
}
<div class="wrapper"> <!-- Just to make things a bit smaller -->
  <p>
  Example of an 4:3 aspect ratio, filled by an image with an 1:1 ratio.
  </p>
  <div class="image-container ratio-4-3"> <!-- Lets go for a 4:3 aspect ratio -->
    <img src="https://placekitten.com/1000/1000/" alt="Kittens!" />
  </div>
  <p>
  Just place other block elements around it; it will work just fine.
  </p>
</div>


3

Puede lograr eso usando SVG.

Depende de un caso, pero en algunos es realmente útil. Como ejemplo, puede establecer background-imagesin establecer una altura fija o usarlo para incrustar youtube <iframe>con relación 16:9yposition:absolute etc.

Para 3:2conjunto de proporcionesviewBox="0 0 3 2" y así sucesivamente.

Ejemplo:

div{
    background-color:red
}
svg{
    width:100%;
    display:block;
    visibility:hidden
}

.demo-1{width:35%}
.demo-2{width:20%}
<div class="demo-1">
  <svg viewBox="0 0 3 2"></svg>
</div>

<hr>

<div class="demo-2">
  <svg viewBox="0 0 3 2"></svg>
</div>


3

Una forma sencilla de mantener la relación de aspecto, utilizando el elemento de lienzo.

Intente cambiar el tamaño del div a continuación para verlo en acción.

Para mí, este enfoque funcionó mejor, así que lo estoy compartiendo con otros para que ellos también puedan beneficiarse de él.

.cont {
  border: 5px solid blue;
  position: relative;
  width: 300px;
  padding: 0;
  margin: 5px;
  resize: horizontal;
  overflow: hidden;
}

.ratio {
  width: 100%;
  margin: 0;
  display: block;
}

.content {
  background-color: rgba(255, 0, 0, 0.5);
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  margin: 0;
}
<div class="cont">
  <canvas class="ratio" width="16" height="9"></canvas>
  <div class="content">I am 16:9</div>
</div>

¡También funciona con altura dinámica!

.cont {
  border: 5px solid blue;
  position: relative;
  height: 170px;
  padding: 0;
  margin: 5px;
  resize: vertical;
  overflow: hidden;
  display: inline-block; /* so the div doesn't automatically expand to max width */
}

.ratio {
  height: 100%;
  margin: 0;
  display: block;
}

.content {
  background-color: rgba(255, 0, 0, 0.5);
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  margin: 0;
}
<div class="cont">
  <canvas class="ratio" width="16" height="9"></canvas>
  <div class="content">I am 16:9</div>
</div>


Sí, me ayudó, ahora puedo usarlo para configurar la altura div del padre de la imagen)
Alex

2

Digamos que desea mantener el Ancho: 100 px y la Altura: 50 px (es decir, 2: 1) Simplemente haga estos cálculos:

.pb-2to1 {
  padding-bottom: calc(50 / 100 * 100%); // i.e., 2:1
}



0

Usé una nueva solución.

.squares{
  width: 30vw
  height: 30vw

A la relación de aspecto principal

.aspect-ratio
  width: 10vw
  height: 10vh

Sin embargo, esto es relativo a toda la ventana gráfica. Entonces, si necesita un div que sea el 30% del ancho de la ventana gráfica, puede usar 30vw en su lugar, y como conoce el ancho, puede reutilizarlos en altura usando la unidad calc y vw.


77
¿No es esto exactamente lo que ya se describió la segunda respuesta mejor calificada?
rnevius

-4

Si toda la estructura del contenedor se basara en porcentajes, este sería el comportamiento predeterminado, ¿puede proporcionar un ejemplo más específico?

A continuación se muestra un ejemplo de lo que quiero decir, si toda su jerarquía principal se basara en%, cualquier ajuste de la ventana del navegador funcionaría sin ningún js / css adicional, ¿no es posible con su diseño?

<div style="width: 100%;">
   <div style="width: 50%; margin: 0 auto;">Content</div>
</div>

1
Vea mi edición de la pregunta original. No veo dónde esta técnica mantendría la relación de aspecto, la altura no cambiaría.
jackb
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.