DIA 16 / 2014

El poder de las sombras en CSS3

Un recorrido por las funciones básicas de las propiedades box-shadow y text-shadow a priori poco relevantes. Pero pueden y de hecho tienen, un potencial enorme desconocido para crear bordes, falsos gradientes, relieves y incluso iconos. A lo largo del artículo describiremos alguno de los usos más insospechados de las sombras en CSS3, así como un caso práctico paso a paso.


Crear sombras en textos o cajas con CSS no supone a priori nada nuevo en el mundo de la maquetación, sin embargo, tras estas sencillas dos propiedades, se esconde un potencial enorme poco explotado por desconocimiento o por falta de creatividad.

¿Cómo funcionan las sombras?

Hablar de sombras en CSS es hablar de las básicas y reconocidas propiedades text-shadow y box-shadow. La primera sólo aplicable a textos y la segunda a cualquier caja y/o bloque; pero antes de entrar en materia, repasemos su sintaxis:

Sintaxis básica de sombras para textos
text-shadow:-Izq/+Der -Arriba/+Abajo Radio Color

Sintaxis básica de sombras en cajas o bloques
box-shadow:Int/Ext -Izq/+Der -Arriba/+Abajo Radio Propagación Color

Al controlar los textos, los valores -Izq/+Der desplazan la sombra horizontalmente hacia un lado u otro dependiendo del signo positivo o negativo asignado, así como -Arriba/+Abajo define verticalmente su ubicación. El Radio controla la extensión del difuminado de la sombra y el Color puede asumir valores Hexadecimal, RGB, RGBA, HSL o HSLA como lógicamente se puede intuir.

Las cajas o bloques funcionan de forma similar, aunque con algunos valores adicionales: Pueden ser Interna/Externa, de esta manera si no definimos este valor se comportará como sombra externa por defecto, sólo si colocando el valor inset reconocerá la sombra como interna a la caja aplicada.

¡CUIDADO!
Si declaramos la sombra interna, los valores -Izq/+Der y -Arriba/+Abajo se invertirán, es decir, horizontalmente se comportará así +Izq/-Der y verticalmente se comportará así +Arriba/-Abajo.

Bajo el nombre de propagación (disculpad mi traducción muy libre) se esconde la posibilidad de extender más o menos la sombra. Puede tomar signo positivo haciendo que se propague más o negativo disminuyendo dicha extensión. Es un concepto un poco abstracto al ser leído, pero en posteriores ejemplos prácticos será más fácil asimilarlo.

NOTA PARA DESPISTADOS
El orden en los valores de la propiedad es fundamental, por ello es imprescindible no confundirse a la hora al incluir unos y omitir otros. Además existen otras reglas no escritas sobre cómo se comportan:

  • Si iniciamos a cero el valor Radio, la sombra se convertirá en dura, sin difuminado: box-shadow: 1px 0 0 0 red;
  • Podemos omitir y no declarar el valor Propagación, ni Radio, pero el navegador los tomará por defecto como valor 0
  • El parámetro Radio es el único que no puede tomar valores negativos.
  • No es necesario poner el tipo de valor (ejemplo 0px) si es cero: box-shadow: 1px 0 0 red;
  • Podemos añadir tantas sombras como queramos siempre que vayan separadas por comas: box shadow: 1px 0 5px red, 2px 1 2px blue, 0 2px 0 green;
  • Ni el valor inset ni la propiedad Propagación son válidas en text-shadow.

Esto ya lo sabía, ¿y ahora qué?

Con todo ese material, ya podemos hacer cosas increíbles, como bordes, gradientes, efectos 3d en textos, dibujos, iconos…

Crear bordes

La ventaja al usar sombras en lugar de la típica propiedad border, es la virtud de las sombras para no añadir grosor real a la caja, es decir, si tenemos un div de 50 pixels de ancho, al añadir border: 1px solid red; el ancho de caja pasaría a ser 52px.

Además podemos añadir todas las sombras que queramos, por tanto podremos crear cientos de bordes en una misma caja con una sola propiedad. Sin embargo existe aún otra ventaja, podemos añadir bordes internos, tantos como necesitemos. Aquí una muestra:

See the Pen Bordes con sombras by Nando Muñoz (@Silencespainter) on CodePen.8811

Recurso: Mixin SASS bordes con box-shadow
Con el fin de agilizar esta tarea, creé un mixin para SASS que automatiza todo el proceso. Pese a no ser muy complejo, es una buena manera de ahorrarnos tiempo. Podéis acceder a él a través de mi repositorio GitHub o verlo en acción en mi Codepen.

Gradientes y relieves

Por la propia naturaleza de las sombras internas, se pueden crear falsos gradientes radiales. Combinando varias se pueden conseguir efectos muy interesantes, ya depende de tu imaginación y/o destreza.

See the Pen Gradiente con Sombras by Nando Muñoz (@Silencespainter) on CodePen.8811

Los relieves y bajorrelieves con sombras de tonos más claros y oscuros son una buena solución para crear efectos 3D en textos:

See the Pen Relieves en textos con sombras by Nando Muñoz (@Silencespainter) on CodePen.8811

Dibujando con sombras

Jugando con la dureza de las sombras en los bloques y su capacidad de replicarlas hasta casi el infinito, se pueden hacer maravillas artísticas como las elaboradas por Katy DeCorah con su pixel art o la mona lisa de Jay Salvat.

Desde el punto de vista estético o experimental son una delicia, pero en la práctica parece muy poco aplicable al trabajo diario, no sólo por la compatibilidad entre navegadores, sino la carga que supone del lado del cliente ‘renderizar’ tan información. Herramientas como Image2CSS hacen más liviano el proceso, pero no disminuye la problemática anterior.

Icono responsive (Icono hamburguesa)

El clásico y denostado en ocasiones icono famoso de las tres franjas, es uno de los quebraderos de cabeza que más dudas nos genera a todos los que diseñamos webs responsive. Existen mil maneras de mostrarlo: mediante un png, un svg reescalable o el clasico icono tipográfico del estilo Font Awesome.

Pues bien, ahora os presento una nueva manera de generarlo, sólo necesitamos conocer los pormenores de la propiedad: Box-shadow y los Pseudoelementos (*::after *::before). A continuación paso a explicar paso a paso como elaborar un mixin en SASS muy sencillo:

// SASS
@mixin icon-menu($size, $color, $colorHover){ ...  }

.icon-menu {
    display: block;
    @include icon-menu(5em,gray, black);
}

Creamos un enlace con la clase icon-menu, ese será el único código HTML necesario. A continuación, creamos el mixin con los parámetros $size: tamaño del ancho del icono, $color: el color del icono y $colorHover: el color del icono al pasar el puntero sobre él. Ya sólo basta declarar el @include en la clase .icon-menu junto al resto de propiedades que gustemos añadir. Pero vayamos al grano con el mixing, pues es lo realmente importante:

// SASS
@mixin icon-menu($size, $color, $colorHover){

    width: $size;
    height: ($size/4);
    background-color:  $color;
}

Definimos el ancho con el parámetro $size, y el alto como cuatro veces menor al tamaño del ancho, además del color del icono con $color. Así creamos la franja superior del icono, ya sólo faltan dos más ¿Cómo lo hacemos?

//SASS
@mixin icon-menu($size, $color, $colorHover){
    …
    box-shadow:
        0 ($size/2)  $color, // Franja segunda
        0 ($size)     $color; // Franja tercera
}

Llegó el momento de crear las dos franjas restantes con box-shadow, la clave es jugar con la altura. En el primer caso, el alto será la mitad del ancho ($size/2) y en el segundo se corresponde con el ancho exacto. Un punto importante es generar la dureza de la sombra, al no escribirla toma el valor 0 por defecto, pero podríamos también definirla así: box-shadow: 0 ($size/2) 0 0 $color, 0 $size 0 0 $color;

Con esto ya tenemos el icono responsive listo, pero tiene un pequeño problema, si pasaramos el ratón sobre él, sólo reconocerá la franja superior además de provocar problemas de solapamiento con el resto de elementos próximos al icono {recordemos que las sombras, son sombras y no bloques como tal } Para solventar este pequeño problema recurrimos a los pseudoelementos:

//SASS
@mixin icon-menu($size, $color, $colorHover){
    …
    &::after {
        content:"";
        width: $size;
        height: $size + ($size/4);
        display: block;
    }
}

Añadimos un $::after sin contenido, lo definimos como bloque con display:block, determinamos el ancho con $size y el alto será el valor del ancho más la cuarta parte de dicho ancho. Al ser cinco franjas, tres visibles y dos transparentes, todas ellas de las mismas dimensiones, el alto no coincide con ancho. Se podría conseguir la cuadratura perfecta jugando con las dos espacios entre las tres franjas visibles, sólo sería cuestión de jugar con las proporciones, pero esta me parece la forma más sencilla de crear el icono.

TRUCO
Para testar el hasta ahora invisible pseudoelemento podeis añadirle un background de un color que contraste y así comprobareis que sigue ahí solapado ;D
//SASS
@mixin icon-menu($size, $color, $colorHover){
    …
    &:hover {
        background-color: $colorHover;
        box-shadow:
            0 ($size/2) $colorHover,
            0 ($size)   $colorHover;
    }
}

Ya sólo falta definir cómo responde ante el selector :hover. Usamos la variable $colorHover y volvemos a definir las sombras pero cambiando el color. Ya tenemos nuestro mixin lista para usarse, y con el mínimo de líneas de código posible.

Todo no es color de rosa y ahora nos tocaría testar su comportamiento en los navegadores no tan modernos y/o crear fallbacks si lo creemos necesario.

Espero que estos desconocidos usos de las sombras os sirvan para usarlas de formas más creativas.