Krypton Solid

Repensar el SVG receptivo – Smashing Magazine

Repensar el SVG receptivo – Smashing Magazine

Si aún no ha visto la técnica de iconos receptivos de Joe Harrison, lo más probable es que esté tan impresionado como yo cuando la descubrí por primera vez. En este artículo, me gustaría explorar lo que podemos hacer con SVG más allá de los gráficos vectoriales escalables «tradicionales» que se utilizan para reemplazar los PNG de mapa de bits.

De hecho, podemos ver SVG como módulo independiente que encapsula CSS para la personalización de vistas, así como el comportamiento receptivo que también encapsula JavaScript para la lógica de interacción.

Ahora, profundicemos un poco más en esta técnica.

SVG receptivo: el método del vagabundo

El sitio web Responsive Icons de Harrison se implementa de manera bastante simple. Sigue una técnica muy conocida: sprites de imágenes. Si no estás familiarizado con los sprites, déjame explicarte. El spriting de imágenes es una técnica que se utilizaba anteriormente solo para imágenes ráster para combatir el rendimiento deficiente de la red. La idea es combinar muchas imágenes pequeñas en un solo archivo, por lo que el cliente tiene que descargar solo una imagen del servidor.

También usaría CSS para cambiar la imagen y mostrar solo la parte que necesita para un elemento en particular, ahorrándole al usuario la sobrecarga de tener que descargar cada imagen individualmente. (Leer más sobre sprites en CSS-Tricks.)

La técnica de Harrison hace lo mismo, excepto con SVG en lugar de PNG. Así es como se verían todos sus iconos combinados en un solo archivo:

Todos los iconos combinados en un solo archivo SVG.
Todos los iconos combinados en un solo archivo SVG. Vista grande.

Este archivo, entonces, se establecería como fondo de un contenedor en el que se debería mostrar uno de estos íconos:

.icon {
  width: 300px;
  height: 300px;
  background: url(../images/home_sprite.svg);
  background-position: center top;
}

El ejemplo anterior es bastante simple pero tiene algunos problemas. La solución no es lo suficientemente portátil. De hecho, se necesitan dos partes para que el método funcione: CSS externo y un sprite SVG.

SVG receptivo: el método del pobre

Debido a que CSS se puede definir dentro de SVG, revisemos el ejemplo anterior para encapsular el icono y hacerlo portátil.

Primero, eliminemos todos los cambios espaciales de los íconos en el objeto. Por supuesto, eso nos deja con un desorden de íconos en capas:

Ver la pluma inxym por Ilya Pukhalski.

Ver la pluma inxym por Ilya Pukhalski.

Luego, reorganicemos todas las formas y agrúpelas por ícono, agregando un .icon clase a cada grupo, así como números para poder identificar cada uno que queramos (así, #home_icon_0, #home_icon_1 y hasta #home_icon_8):

<svg>
  <g id="home_icon_0" class="icon">
    <!-- paths and shapes -->
  </g>

  <!-- ... -->

  <g id="home_icon_8" class="icon">
    <!-- paths and shapes -->
  </g>
</svg>

Ahora, estamos listos para agregar consultas de medios, de modo que podamos seleccionar el ícono en el archivo SVG que queremos mostrar. Para ello, escribiendo el CSS directamente en el <svg> la etiqueta es posible usando <defs> etiquetas.

<svg>
  <defs>
    <style>
    /* Hide all of the icons first. */
    .icon {
      display: none;
    }

    /* Display the first one. */
    #home_icon_0 {
      display: block;
    }

    /* Display the desired icon and hide the others according to the viewport's size. */
    @media screen and (min-width: 25em) {

      #home_icon_0 {
        display: none;
      }

      #home_icon_1 {
        display: block;
      }
    }

    @media screen and (min-width: 30em) {
      #home_icon_1 {
        display: none;
      }

      #home_icon_2 {
        display: block;
      }
    }

    /* And so on */

    </style>
  </defs>

<!-- Icon groups go here -->

</svg>

Como resultado, el mismo icono ahora se adapta al tamaño de la ventana gráfica, excepto que ahora, las reglas CSS, las consultas de medios y las formas SVG están encapsuladas en el propio archivo SVG. Cambie el tamaño de su navegador para ver cómo funciona el siguiente ejemplo:

Ver la pluma LaMWvX por Ilya Pukhalski.

Ver la pluma LaMWvX por Ilya Pukhalski.

SVG receptivo: el método del hombre con una pistola

El ejemplo anterior se ve mejor que el primero, pero quedan preguntas:

  • ¿Podría entregarse el SVG receptivo de una mejor manera?
  • ¿Es posible seguir un enfoque receptivo para diseñar los iconos y personalizar elementos, en lugar de simplemente ocultar y mostrar partes del archivo?

Mirando los trucos de reestructuración de diseño y coreografía de contenido en los que confiamos para el diseño web receptivo a diario, podemos mejorar nuestro prototipo incluso todavía. Usaremos diseño receptivo, reestructuración de formas y transformaciones para adaptar los íconos a diferentes tamaños de ventana gráfica.

Primero, redibujemos el ícono de casa más grande y detallado en nuestro archivo de sprite SVG, dividiendo todos los caminos y formas unidas en formas elementales. El resultado es mucho más legible y ahora es posible aplicar cualquier transformación a cualquier parte del icono:

Ver la pluma Azqyn por Ilya Pukhalski.

Ver la pluma Azqyn por Ilya Pukhalski.

Nuestro icono redibujado se ve igual que el más grande del objeto, pero contiene muchas más formas y ocupa un poco más de espacio. La magia es que agregaremos consultas de medios y transformaciones a la nueva variante, transformando las formas del ícono en sí para obtener el mismo resultado que el sprite SVG:

<svg>
  <defs>
    <style>
    @media screen and (max-width: 65em) {

      #door-shadow, #tube-shadow, .backyard {
        display: none;
      }

      #door-body {
        fill: white;
      }

      #door-handle {
        fill: #E55C3C;
      }

      #door-body, #door-handle {
        -ms-transform: translate(0,0);
        -webkit-transform: translate(0,0);
        transform: translate(0,0);
      }

      #window {
        -ms-transform: translate(0,0) scale(1);
        -webkit-transform: translate(0,0) scale(1);
        transform: translate(0,0) scale(1);
      }

      #house-body {
        -ms-transform: scaleX(1) translate(0, 0);
        -webkit-transform: scaleX(1) translate(0, 0);
        transform: scaleX(1) translate(0, 0);
      }

      #tube-body {
        -ms-transform: translate(0, 0);
        -webkit-transform: translate(0, 0);
        transform: translate(0, 0);
      }

      #tube-upper {
        -ms-transform: translate(0, 0);
        -webkit-transform: translate(0, 0);
        transform: translate(0, 0);
      }
    }

    /* And so on */

    </style>
  </defs>

<!-- Icon groups go here -->

</svg>

Una vez que hayamos agregado un poco de magia de transformación, el ícono se comportará como el sprite SVG de Joe Harrison, pero contendrá toda la lógica dentro de sí mismo. Abra el siguiente ejemplo en una nueva ventana y cambie su tamaño para ver todas las variantes de iconos.

Ver la pluma hFLDG por Ilya Pukhalski.

Ver la pluma hFLDG por Ilya Pukhalski.

Adaptar el icono al tamaño del contenedor principal

Una cosa más. También es posible hacer que el icono responda a los cambios en su contenedor principal (al menos el ancho y el alto).

Para hacer esto, primero intenté cargar el archivo SVG en un img elemento, envuelto en un div. Pero ni siquiera una consulta de medios en el archivo SVG pareció funcionar.

Mi segundo intento fue cargar el icono en el flexible object elemento, envuelto en un div. Hacer eso hizo que todas las consultas de los medios funcionaran. Y ahora también es posible hacer que un objeto llene el espacio de su padre. (No olvide configurar los atributos de ancho y alto de la svg elemento al 100% o eliminarlos por completo.)

<div style="width: 100%; margin: 0 auto;">
  <object>
    <embed src="https://www.smashingmagazine.com/2014/03/rethinking-responsive-svg/responsive3.svg" style="width: 100%; height: auto;" />
  </object>
</div>

En cuanto a otras formas de incrustar SVG con consultas y transformaciones de medios, puede usar SVG como imagen de fondo para cualquier elemento de bloque. También se permite el SVG en línea, pero las consultas de medios responderían a la ventana gráfica.

El siguiente ejemplo demuestra cómo responde el icono a diferentes tamaños de contenedores. Las consultas de medios en el SVG manejan cómo se dibuja el ícono, de acuerdo con las dimensiones en las que se va a representar el SVG. Aquí hay ocho bloques con diferentes tamaños, incrustados con una y las mismas Archivo SVG.

Ver la pluma hszLl por Ilya Pukhalski.

Ver la pluma hszLl por Ilya Pukhalski.

Agregar JavaScript a SVG

¡Más buenas noticias! El archivo SVG puede encapsular no solo CSS, sino también JavaScript. En esencia, podemos considerar un archivo SVG incluido como un módulo independiente al que se puede aplicar cualquier lenguaje de marcado antiguo.

JavaScript en SVG funcionará perfectamente cuando esté integrado en línea en el <object> elemento. Un mundo tan maravilloso, ¿eh?

Soporte del navegador

Este último y más complejo método de usar SVG con media queries y transformaciones se comporta perfectamente en las siguientes versiones del navegador:

  • Internet Explorer 9+
  • Firefox 17+
  • Chrome 17+
  • Opera 15+
  • Safari 6.0 o superior
  • Safari en iOS 6.0 o superior
  • Navegador de Android en Android 3.0+

La técnica podría funcionar en las versiones antiguas de los navegadores, pero algunas transformaciones, como el escalado, no se aplicarían.

Conclusión

Los íconos SVG receptivos se pueden usar de muchas maneras, incluidas las siguientes:

  • anuncios receptivos (el contenido del anuncio ocuparía el espacio que le otorga el documento y, considerando que CSS y JavaScript están permitidos, la mayor parte de la acción estaría contenida en un solo archivo SVG por anuncio);
  • logotipos;
  • iconos de aplicaciones.

Debo decir que no hay nada de malo en la técnica de los sprites propuesta por Joe Harrison. ¡Funciona y es necesario para algunos propósitos!

¿Pensamientos? ¿Realimentación? Espero sus comentarios en la sección de comentarios a continuación.

Saludos y diviértete!

Otras lecturas en SmashingMag:

Deja un comentario