Css aspect ratio (&2): la altura manda y define las medidas

La altura manda: segunda parte dedicada a cómo conseguir con puro CSS que los elementos mantengan la relación de aspecto (aspect ratio) deseada en base a su altura.

Css aspect ratio (&2): la altura manda y define las medidas

Por Kseso ✎ 4

Css aspect ratio: the heights ruleEn el artículo anterior sobre la relación de aspecto con Css, además de una breve explicación de qué es, me centraba en cómo lograr cajas con cualquier "aspect ratio" donde la relación es definida por su anchura del elemento.

Pero pese a que pueda ser la situación más habitual, también es cierto que habrá ocasiones donde se necesite que sea la altura (height) la que defina las medidas finales (computadas) de los elementos.

En este artículo, y como complemento al previo, vamos a centrarnos en este caso concreto: lograr cajas con cualquier relación de aspecto (aspect ratio) con puro Css y que sus medidas sean en función de la altura. Con independencia de cuál sea su altura final computada. O lo que es lo mismo, volvemos a encontrarnos con el RWD y los distintos viewports.

Considerandos previos

Al plantearse tener cajas con una determinada relación de aspecto creo que lo primero a cumplirse es que no deberían sobrepasar las dimensiones de la ventana. Esto es, verse en su totalidad de un solo golpe de vista. Si parte de ella queda oculta y hay que hacer scroll como que se pierde la proporcionalidad.

El 'aspect ratio' con css basado en las alturas posíblemente se pueda obtener en base a la técnica usada en el artículo anterior. Eso sí, estaría supeditada a usar varias cajas (divitis) únicamente por un motivo estético (de apariencia). Cuestión que ni me motiva a intentarlo y que es desaconsejable (la divitis por estética).

Y por último y principal: este blog si tiene un objetivo claro es ser divulgativo de Css, especialmente de aquellos aspectos menos conocidos con independencia de su factor de uso "industrial" inmediato. Así que...

Css aspect ratio función de la altura

Como siempre, para aplicar los estilos necesitamos un código html. Vamos con el básico de la demo en base a la segunda consideración:

<div class='elemento'> <!-- añade el html necesario --> </div>

Para lograr una relación de aspecto basada en una altura declarada (y por lo tanto que su anchura sea calculada en función de la altura por el navegador) de forma simple no tenemos una propiedad que relacione ambas, pero sí que Css define un valor que lo hace: vh o los valores en función del tamaño del viewport o "viewport-percentage".

.elemento { height: 90vh; }

Con el código anterior sólo cubrimos en parte el primer considerando de este artículo. Ahora necesitamos cumplir el segundo: nada de divitis. En este caso para que la anchura sea proporcional a la altura declara según la relación de aspecto que se necesite recurrimos a otro valor Css: la función calc().

.elemento { height: 90vh; width: calc(90vh * 0.5625);/*para una relación 16:9*/ }

Para las relaciones más comunes es fácil crear el css oportuno de forma sencilla y no repetitiva:

<-- cajas verticales --> <div class='ratio1-2'> <h2>Ratio 1:2</h2> </div> <div class='ratio9-16'> <h2>Ratio 9:16</h2> </div> <div class='ratio3-4'> <h2>Ratio 3:4</h2> </div> <-- cajas horizontales --> <div class='relacion2-1'> <h2>Ratio 2:1</h2> </div> <div class='relacion16-9'> <h2>Ratio 16:9</h2> </div> <div class='relacion4-3'> <h2>Ratio 4:3</h2> </div> [class*='ratio'], [class*='relacion'] { height: 90vh; background: #E74C3C; } [class*='relacion'] {height: 50vh;} /*cajas verticales*/ .ratio9-16 {width: calc(90vh * 0.5625);} .ratio3-4 {width: calc(90vh * 0.75);} .ratio1-2 {width: calc(90vh * 0.5);} /*cajas horizontales*/ .relacion2-1 {width: calc(50vh * 2);} .relacion16-9 {width: calc(50vh * 1.78);} .relacion4-3 {width: calc(50vh * 1.33);}

Ver demo

See the Pen Aspect ratios pure Css: heights rule by Kseso (@Kseso) on CodePen

Objeciones a esta demo

La primera es el soporte o la posibilidad de utilizarlo en realizaciones "industriales". Pese al más que notable soporte de los navegadores en sus últimas versiones tanto a las unidades viewport-percentage y a la función Css calc() al usarlas conjuntamente la sorpresa desagradable viene de Chrome que no soporta las unidades viewport-percentage en la función Css calc().

La segunda y menor contra es que como viste antes hay que definir dos veces el valor de la altura: en la propiedad height y en la función Css calc() para cada clase o relación.

¿Se podría ir un paso más allá y solventar este segundo hándicap?

Automatizando las relaciones de aspecto con puro Css

Si sigues, aunque sea sólo un poquito este blog, recordarás que en los últimos artículos, además de mencionar a la función calc(), también ha salido otra de las novedades de Css: sus variables. Aquí un artículo de iniciación a ellas y el último documento del W3c sobre las variables.

EN base a estas dos "novedades" de Css sí que podemos automatizar un poco más este aspecto (y otros muchos más):

:root { var-vertical: 90vh; var-horizontal: 50vh; var-ratio9_16: 0.5625; var-ratio4_3: 1.33; }

Comenzamos definiendo las variables Css: las dos primera serían para declarar las alturas en las cajas que hemos manejado en el ejemplo anterior. Las dos siguientes para las relaciones de aspecto 16:9 y 9:16.

Y para aplicar estos valores definimos las clases oportunas que incluyan estas variables:

.ratio9-16 { height: var(vertical); width: calc(var(altura) * var(ratio9_16)); } .ratio3-4 { height: var(horizontal); width: calc(var(horizontal) * var(ratio4_3)); }

Sencillo, ¿no?. De esta manera sólo es necesario cambiar el valor en 'var-vertical' y/o 'var-horizontal' para que todo lo demás cambie manteniendo la relación de aspecto deseada.

Ramajero Argonauta, Enredique Amanuense de CSS.
#impoCSSible inside
Dicen que, en español, EsCss es el mejor blog de CSS. Posíblemente exageren.
@Kseso EsCss Don Kseso Kseso

Comentarios: 4

  1. Excelente justo lo que necesitaba

    ResponderEliminar
  2. Con esto también se resuelve una pregunta clásica en foros y blogs, que es la de usar una imagen de fondo en un bloque sólo para ella, y que se comporte como una imagen real (si tiene un ancho a porcentaje, que la altura se ajuste proporcionalmente).

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    "http://www.w3c.org/TR/1999/REC-html401-19991224/loose.dtd">
    <html>
    <head>
    <style type="text/css">
    .miclase {
    width: 50%;
    background-color: yellow;
    background-size: cover;
    background-image: url(http://img220.imageshack.us/img220/8342/kavanaghproa.jpg);
    margin: 5% 25% 0;
    resize: horizontal;
    overflow:auto;
    }
    .miclase:before {
    content: '';
    display: block;
    padding-top: 75%;
    width: 20px;
    background-color: rgba(255,0,0,.5);
    }
    </style>
    </head>
    <body>
    <div class='miclase'></div>
    </body>
    </html>


    Todavía nos queda el asunto del 'alt=', que no se le puede poner a un 'div'; pero es un detalle.

    ResponderEliminar
    Respuestas
    1. Hey! Furoya
      Creo que esta aplicación práctica a un caso tan común amerita un artículo.
      ¿Tienes un rato libre y te apetece? ;-)

      Un saludo

      P.D.: el alt='' lo podrías emular con un data-alt='' (por ejemplo) y una vez creado hasta mostrarlo con ::after {content: attr(data-alt);.

      Eliminar
    2. Es que no se me ocurre cómo mostrar el falso texto alternativo solamente si no se carga el fondo.
      Tampoco recuerdo si hay una pseudoclase para "imagen sin cargar". (':-moz-broken' da algunas posibilidades, pero ignora a la función 'url()' para fondos)

      Siguiendo tu recomendación, lo mejor para simular el 'alt' que se me ocurrió es

      <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
      "http://www.w3c.org/TR/1999/REC-html401-19991224/loose.dtd">
      <html>
      <head>
      <style type="text/css">
      .miclase {width: 50%; background-size: cover;
      background-image: url(http://img220.imageshack.us/img220/8342/kavanaghproa.jpg);
      margin: 5% 25% 0; resize: horizontal; overflow:auto; }
      .miclase:before {content: ''; display: block; padding-top: 75%; width: 20px;
      background-color: rgba(255,0,0,.5); }
      .miclase:after {content: attr(data-alt); position: absolute; z-index: -1;
      margin: -35% auto auto 1%; font: menu; }
      </style>
      </head>
      <body class=warning>
      <div class='miclase' data-alt="Edificio Kavanagh."></div>
      </body>
      </html>


      Pero sirve solamente para imágenes opacas.

      Me parece un aporte más bien pobre para un artículo, me animé a ponerlo en un comentario porque creo que hasta aquí, da.
      Quizá juntando más usos prácticos del método, aunque va a llevar un tiempo hasta que aparezcan y se pueda redactar algo al nivel del resto de las entradas del blog.


      Otro saludo, y seguí publicando estas ideas, que después me pongo a hacer experimentos y me olvido de hacer mi trabajo.
      :-\

      Eliminar

EsCss RSS del Blog RSSS Comentarios Humans.txt ᛯ Diseno por Kseso SiteMap