LESS, el lenguaje de hojas de estilo dinámico

Sigue a Genbetadev

Less



¿Cuantas veces no hemos echado de menos el poder usar variables en nuestras hojas de estilo CSS a la hora de añadir colores y otros parámetros?. ¿Cuantas veces no hemos echado en falta la posibilidad de declarar funciones para código repetitivo?. Muchas ¿verdad?.

Por desgracia, CSS no es un lenguaje de programación y no dispone de ninguna de esas cosas que tanto echamos de menos. Parece que Alexis Sellier (aka @cloudhead) también echaba de menos toda esa funcionalidad, y en lugar de quejarse y suspirar como hacemos nosotros, decidió hacer algo al respecto.

Así que inspirado por sass desarrolló una potente herramienta que permitía añadir todas esas cosas que los programadores (que somos muy quisquillosos) echábamos tanto de menos al trabajar con CSS. Hoy vamos a hablar sobre LESS, el lenguaje de hojas de estilo dinámico.

¿Qué es LESS?

LESS extiende CSS para dotarlo de un comportamiento dinámico a través de variables, mixins, operaciones y funciones.

¿Cómo funciona?

Para utilizar LESS no necesitas un plug-in ni nada especial. La idea detrás de la herramienta es que el navegador interpreta código CSS normal y corriente producido a través de un proceso de compilación de nuestras plantillas escritas en LESS.

Lo único que cambia es la forma que tenemos de compilar las plantillas LESS. Si usamos un servidor Web basado en Node.js o bien servimos nuestras hojas de estilo CSS a través de un script en cualquier lenguaje como PHP, Python, Ruby o Perl (por ejemplo), podemos compilar nuestras plantillas LESS en tiempo de ejecución (del servidor) utilizando para ello Node.js

Si queremos utilizar Node.js debemos de crear un archivo JavaScript que se encargue de cargar nuestra plantilla LESS y compilarla al vuelo devolviendo el archivo CSS compilado. Si usamos un servidor web Node.js es bastante sencillo:

var less = require('less');
var fs = require('fs');
fs.readFile('styles.less', 'utf8', function(err, data) {
        if (err) throw err;
        less.render(data, function(e, css) {
                console.log(css);
        });
});

Si no entiendes el código anterior, no te preocupes demasiado, no es necesario utilizar Node.js para usar LESS en nuestros proyectos, es una opción.

Si no ejecutamos nuestro sitio web sobre un servidor Node.js podemos seguir compilando nuestras plantillas en tiempo de ejecución usando un sencillo script para ello. Voy a poner el código de ejemplo en Python, traducirlo a otro lenguaje es algo trivial:

import subprocess
node = subprocess.Popen(['node', 'compiler.js'], stdout=subprocess.PIPE)
print node.communicate()[0]

Como puedes ver, llamamos a Node.js para ejecutar un archivo compiler.js que contiene el código anterior y lo hacemos desde un servidor web con mod_python o Twisted (por ejemplo) utilizando el módulo subprocess de Python.

También podemos utilizar el script less.js que podemos descargar directamente desde la página del proyecto para compilar el archivo LESS desde el propio cliente. A diferencia del método anterior, estaríamos utilizando ciclos de CPU del cliente en lugar del servidor para compilar el código:

<link rel="stylesheet/less" type="text/css" href="styles.less">
<scipt type="text/javascript" src="less-1.1.3.js"></scipt></link>

Es muy importante que incluyamos primero las hojas de estilo. El script compilará nuestro archivo LESS y añadirá un elemento style a nuestro DOM con el código compilado listo para su uso.

Existe además otra manera (que es la que al menos yo recomiendo) que consiste en compilar previamente nuestras plantillas LESS con la utilidad de linea de comandos lessc (LESS Compiler) para generar los archivos CSS necesarios y después incluirlos normalmente en nuestro documento:

genbeta@dev ~ $ lessc styles.less styles.css
Si queremos usar una versión minificada del archivo solo tenemos que añadir la opción -x:
genbeta@dev ~ $ lessc styles.less styles.css -x

También puede usarse la técnica de invocar al compilador desde nuestros scripts en PHP, Python, Ruby o lo que sea si servimos los archivos CSS de forma dinámica:

import subprocess
node = subprocess.Popen(['lessc', 'styles.less', '-x'], stdout=subprocess.PIPE)
print node.communicate()[0]

Una vez tenemos claro qué es y como funciona LESS, vamos al lio.

Variables

Las variables nos permiten definir en un solo lugar un valor que será usado en múltiples sitios de nuestro código CSS. Esto nos permite reutilizar las variables y en caso de cambiar por ejemplo un color corporativo, tendremos que cambiarlo solo en un lugar de nuestro archivo CSS. Las variables nos permiten aplicar el principio DRY (Dont Repeat Yourself).

// LESS
@color: #a8b317;
a {
    color: @color;
}
h2 {
    color: @color;
}
El código LESS anterior se convertiría en el siguiente código CSS al compilarse.
// CSS
a {
    color: #a8b317;
}
h2 {
    color: #a8b317;
}

Como ya hemos dicho, se pueden utilizar operaciones, por lo tanto podemos sumar, restar, multiplicar y dividir variables:

@minWidth: 20%;
@columnLeft: @minWidth * 2;
@columnRight: @columnLeft + @minWidth;
@color: #4a785b;
.sideLeft {
    background-color: @color + #111;
    width: @columnLeft;
}
.sideRight {
    background-color: @color;
    width: @columnRight;
}

LESS entiende la diferencia entre un color o una unidad al realizar operaciones, lo cual es una pasada. El código anterior daría como resultado al compilarse:

.sideLeft {
    background-color: #5b896c;
    width: 40%;
}
.sideRight {
    background-color: #4a785b;
    width: 60%;
}

Como ya has podido apreciar por ti mismo, LESS abre la puerta a un mundo maravilloso de oportunidades sin límite.

Mixins

Los Mixins te permiten embeber todas las propiedades de una clase dentro de otra clase simplemente incluyendo el nombre de la misma como una de sus propiedades.

.round-corners (@radius: 5px) {
    -moz-border-radius: @radius;
    -webkit-border-radius: @radius;
    border-radius: @radius;
}
#header {
    .round-corners;
}
Creo que no es necesario que exprese lo excitante que resulta esto. Pero eso no es todo, te habrás fijado en que he utilizado una variable a modo de parámetro como si de una función se tratara, y seguro que te estás repitiendo abrazado a un osito de peluche y en posición fetal no puede ser, no puede ser, no puede ser…. Pues si, si que puede ser, se le pueden pasar valores como parámetros al invocarlas.
#post {
    .round-corners(16px);
}

Los códigos anteriores darían como resultado el siguiente código CSS:

#header {
    border-radius: 5px;
    -webkit-border-radius: 5px;
    -moz-border-radius: 5px;
}
#post {
    border-radius: 16px;
    -webkit-border-radius: 16px;
    -moz-border-radius: 16px;
}
Esta funcionalidad me deja más excitado que a Antonio Lobato cuando gana Alonso una carrera de F1.

Cuando un mixin recibe más de un parámetro y no queremos escribirlos todos, podemos utilizar la variable especial @arguments

.shadow (@x: 0, @y: 0, @blur: 1px, @color: #000) {
    -moz-box-shadow: @arguments;
    -webkit-box-shadow: @arguments;
    box-shadow: @arguments;
}
.shadow(1px, 2px);

Reglas Anidadas

Cuando programamos en LESS no es necesario que escribamos largos selectores para especificar la herencia de nuestras reglas. Podemos usar selectores anidados dentro de otros selectores. Esto convierte a la herencia en algo limpio y elegante.

#record {
    h1 {
        font-family: Helvetica, Arial, sans-serif;
        font-weight: bold;
        font-size: 2em;
    }
    p {
        font-size: 12px;
        a {
            text-decoration: none;
            &:hover {
                color: red;
            }
        }
    }
}
Este código daría como resultado al compilarse:
#record  h1{
    font-family: Helvetica, Arial, sans-serif;
    font-weight: bold;
    font-size: 2em;
}
#header p {
    font-size: 12px;
}
#header p a {
    text-decoration: none;
}
#header p a:hover {
    color: red;
}
}
La sintaxis de LESS es mucho más clara y elegante que el uso de selectores naturales de CSS.

Funciones de Color

LESS nos ofrece una variedad de funciones para transformar colores. Primero son transformados a HSL y después son manipulados a nivel de canal.

lighten(@color, 10%); // devuelve un color un 10% mas "claro" que @color
darken(@color, 10%); // devuelve un color un 10% mas "oscuro" que @color
saturate(@color, 10%); // devuelve un color un 10% "más" saturado que @color
desaturate(@color, 10%); // devuelve un color un 10% "menos" saturado que @color
fadein(@color, 10%); // devuelve un color un 10% "menos" transparente que @color
fadeout(@color, 10%); // devuelve un color un 10% "más" transparente que @color
spin(@color, 10); // devuelve un color con 10 grados de tono mayor que @color
spin(@color, -10); // devuelve un color con 10 grados de tono menor que @color

Tambien podemos extraer información de un color:
hue(@color); // devuelve el canal `hue` de @color
saturation(@color); // devuelve el canal `saturation` de @color
lightness(@color); // devuelve el canal `lightness` de @color

Espacios de nombres

En ocasiones necesitamos agrupar nuestras variables y mixins para organizarlos mejor, para ofrecer algún tipo de encapsulación o para redistribuirlos. Sea cual fuere nuestra necesidad, LESS nos ofrece una forma sencilla de utilizar espacios de nombres en nuestras plantillas.

#main_header {
    .logo () {
        display: block;
        border: none;
        background: transparent url(../media/logo.png) 0 0 scroll;        
    }
    .slogan { ... }
    .menu { ... }
    ...
}
Usar el nuevo espacio de nombres es igualmente sencillo. Si queremos utilizar la clase .logo en nuestro #header podemos hacerlo de la siguiente forma:
#header a {
    color: green;
    #main_header > .logo;
}

Alcance de Variables (Scope)

El alcance o ámbito de variables en LESS es muy parecido al alcance en otros lenguajes. Primero se busca localmente, si no se encuentra, el compilador busca en el ámbito inmediatamente superior y así sucesivamente.

@var: #333;
#page {
    @var: #fff;
    #header {
        color: @var; // #fff
    }
}
#footer {
    color: @var; // #333
}

Importación

En LESS podemos importar archivos y disponer de todas las variables y mixins que definan de forma automática. La extensión .less es opcional. Para importar un archivo usamos la regla @import. También podemos importar archivos CSS que no serán procesados por el compilador.

Interpolación de cadenas

El valor de las variables puede ser empotrado dentro de cadenas parecido a como se hace en Bash o Ruby pero usando el constructor @{nombe}:

@url: "http://www.genbetadev.com";
background-image: url("@{url}/images/background.png");

Ignorar Elementos

A veces querremos ignorar CSS que no es CSS válido o que pertenece a una sintaxis especial propietaria no disponible en el estándar y que LESS no entiende. En esos casos podemos ignorar partes del archivo utilizando el caracter ~:

.transparente {
    filter: ~"progid:DXImageTransform.Microsoft.AlphaImageLoader(src='image.png')";
}
Toda la definición será ignorada por el compilador de LESS que no la tendrá en cuenta y será añadida al archivo CSS resultante sin cambios.

Emulación de JavaScript

Se pueden evaluar expresiones JavaScript dentro de los archivos .less, para ello, es necesario envolver la expresión con back-ticks (acentos cerrados):

@var: `"genbetadev".toUpperCase() + ' mola!'`;
La expresión anterior daría como resultado:
@var: "GENBETADEV mola!";

Conclusión

LESS es una poderosa herramienta con la que crear hojas de estilo en cascada se convierte en una parte más del proceso de desarrollo de software al elevar a CSS al nivel de lenguaje de programación. Su curva de aprendizaje es muy suave y desde Genbeta Dev recomiendo su uso a todos los desarrolladores web que nos siguen.



Más Información | LESS Wiki

Los comentarios se han cerrado

Ordenar por:

11 comentarios