Como todos devem ter percebido, nos últimos meses o CSS3 e o HTML5 tem ganho um grande destaque no desenvolvimento web. Grandes empresas como o Google, Microsoft, Adobe e Apple estão apoiando fortemente o desenvolvimento web utilizando WebStandards. Caso você já conheça algo sobre CSS, provavelmente deve saber como é complicado a organização desses documentos em um projeto de médio ou grande porte. Dado esses problemas conhecidos, foram surgindo os chamados pré-processadores de CSS, que viabilizam a criação de documentos de estilo, adicionando novas funcionalidades.
Hoje vamos conhecer o LESS, The Dynamic Stylesheet Language. O objetivo dessa biblioteca em javascript é prover uma série de funcionalidades para as, usualmente criadas a mão, folhas de estilos. Recursos tais como, variáveis, mixins (Multiple Inheritance, Traits), mixins parametrizáveis, funções, namespaces, importação, etc. Vamos aprender como utilizar os principais recursos dessa biblioteca em um projeto e como aproveitar o melhor dessa biblioteca para organizar corretamente nossas folhas de estilo.
As variáveis ajudam-nos a definir valores que podem ser utilizados em diversas regras do nosso CSS. Elas possuem escopo assim como em uma linguagem de programação orientada a objetos, trocando em miúdos:
// Arquivo stylesheet.less
// Essa variável foi definida no escopo do arquivo, logo, todas as regras do arquivo podem acessar seu valor.
@siteBackgroundColor: #FF3300; // Laranja
h1 {
// A variável headingColor foi criada no escopo da regra h1, logo, apenas ela e outras regras criadas dentro
// do mesmo escopo tem acesso ao seu valor.
@headingColor: #333333; // Cinza
// Isto significa que, se criarmos uma outra regra chamada &.mainTitle
// Observe o uso do &.classe, isso copia a regra pai e associa uma classe, o output disso seria exatamente h1.mainTitle
&.mainTitle {
// Como essa regra esta contida na regra h1, podemos acessar o valor da variável headingColor.
color: @headingColor;
}
}
h2 {
// Se tentarmos acessar o valor nessa regra, que não encontra-se contida na regra h1, receberemos um erro da biblioteca
// informando que a variável headingColor não encontra-se definida.
color: @headingColor; // Brrrrrr! Error.
}
O que é interessante no uso de variáveis é a reutilização e organização. Imagine uma design guideline onde existem RGBs específicos a serem seguidos, essas cores poderiam ser definidas em um documento chamado color_variables.less e adicionados ao nosso arquivo principal utilizando a clausula @import.
Quando um arquivo LESS é importado, todas as suas variáveis e mixins são adicionados ao arquivo principal. Os escopos serão mantidos e a extensão .less é opcional.
@import “lib.less”
@import “lib”
É possível utilizar pastas nas clausulas de @import:
@import “where/is/my/stylesheet.less”
@import “where/is/my/stylesheet”
No LESS, mixis são como uma espécie de classe CSS que pode ser reutilizada em diversas outras regras. Quando utilizadas, todas as propriedades definidas no mixin são adicionadas a regra onde a mesma foi adicionada, caso um mixin mude, todas as regras que o referenciam serão também modificadas.
Imagine o conceito de mixin como classes CSS orientadas a objeto, o que é interessante do mixin é que temos aqui algo como uma herança múltipla, caso uma mesma instrução seja declarada em mixins diferentes, e esses mixins adicionados a uma regra, o mixin declarado por último terá vantagem na construção final do CSS da regra onde foi adicionado.
.bordered {
border-top: dotted 1px black;
border-bottom: solid 2px black;
}
// Declaramos agora uma regra qualquer que fará uso do nosso mixin.
div.someDiv {
.bordered; // Simples assim, adicionamos todas as propriedades contidas no mixin em nossa regra.
}
div.anotherDiv {
.bordered; // A mesmas propriedades serão adicionadas nessa regra.
}
Quando modificarmos o mixin .bordered, todos os elementos que o estão utilizando serão modificados. Reutilização!
Vamos para um exemplo mais usável para exemplificar como é um mixin parametrizável.
// Bordas arredondadas cross-browser.
// Observe que utilizamos algo parecido com uma função de javascript para declararmos nosso mixin.
// A notação de variável deve ser adicionada (@radius), com isso, criamos uma variável chamada "radius" no escopo
// do mixin que poderá ser utilizada apenas internamente pelo método.
// Observe também que declaramos um valor padrão para o parâmetro, de 5px.
.border-radius( @radius: 5px )
{
// Repare que utilizamos a mesma variável para todas as regras.
border-radius: @radius;
-moz-border-radius: @radius;
-webkit-border-radius: @radius;
}
// Para utilizarmos a regra, seguimos o mesmo padrão
div.someDiv {
.border-radius; // Nesse caso estaremos utilizando o valor padrão de 5px.
}
div.anotherDiv {
.border-radius(10px); // Nessa aplicação, modificamos o valor da propriedade para 10px.
}
É importante destacar que um mixin pode conter diversos parâmetros. Isso pode ser feito da seguinte forma:
// Declaramos um novo mixin
.border-radius-and-color( @radius: 5px, @borderColor: #000000 )
{
.border-radius( @radius ); // Observe que aqui reutilizei o mixin previamente definido. Composição de mixins.
border: 2px solid @borderColor; // Adicionamos agora a cor para a borda.
}
Com o LESS você pode criar suas regras de CSS utilizando uma espécie de hierarquia. Vamos ver como isso funciona na prática.
// Dado o CSS abaixo
div#header #menu {
...
rules
}
div#header #menu li a {
...
more rules
}
div#header #topNav {
...
another rules
}
Com o LESS, o mesmo CSS acima poderia ser escrito da seguinte forma:
// Como utilizar hierarquia com Less
div#header {
#menu {
ul {
li {
}
}
}
#topNav {
}
}
Depois de processado, o CSS será exatamente igual. Você não precisa utilizar esse esquema de hierarquia caso não queira, é importante lembrar que o LESS é apenas uma extensão do CSS, se for de desejo do desenvolvedor, podemos escrever um código LESS sem usar nenhum recurso especial, como se fosse um CSS tradicional.
Com o LESS o seu CSS sabe fazer contas. Qualquer número, cor ou variável pode ser utilizada em uma operação aritmética.
Ele sabe identificar quando estamos utilizando uma cor ou um número, por exemplo:
@base: 5%;
@filler: @base * 2;
@other: @base + @filler;
color: #888 / 4;
background-color: @base-color + #111;
height: 100% / 2 + @filler;
Assim como no javascript, é possível também utilizar parênteses nas suas operações:
width: (@var + 5) * 2;
Na minha opinião um dos recursos mais úteis durante o desenvolvimento de uma aplicação. Podemos efetuar operações em cima de RGBs, por exemplo, imagine que o layout do seu website foi criado baseado-se em apenas uma cor, utilizando diversos tons dessa cor. Com o LESS é possível utilizar métodos pré-definidos como lighten, saturate, darken, fadein, fadeout e spin. Esses métodos retornam sempre um RGB que pode ser utilizado em seu LESS. Vejamos alguns exemplos:
@base: #f04615;
.class {
// Saturo em 5% a cor base.
color: saturate(@base, 5%);
// Utilizo a cor base 25% mais clara
background-color: lighten(@base, 25%);
}
É possível também extrair informações de uma determinada cor para ser utilizada em outra.
Isso é feito a partir dos métodos hue, saturation e lightness.
hue(@color); // retorna o valor do canal 'hue' da cor @color
saturation(@color); // retorna o valor do canal 'saturation' da cor @color
lightness(@color); // retorna o valor do canal 'lightness' da cor @color
Em dado momento necessitamos organizar uma série de mixins e variáveis. Para isto podemos utilizar um conceito presente no LESS chamado Namespaces. Assim como em linguagens de programação orientadas a objetos, que possuem o conceito de pacotes, os namespaces fornecem encapsulação para nossas folhas de estilo. Isso pode ser implementado facilmente utilizando a mesma notação de ID do CSS tradicional. Vejamos.
#bundle
{
.button ()
{
display: block;
border: 1px solid black;
background-color: grey;
&:hover { background-color: white }
}
.tab { ... }
.citation { ... }
}
Verifique que acima, criamos um mixin chamado button dentro do namespace bundle. Para o utilizarmos devemos fazer da seguinte forma:
#header a {
color: orange;
#bundle > .button; // Estamos acessando o namespace 'bundle' e fazendo uma chamada para o mixin 'button'.
}
Uma utilização muito comum dos namespaces é na criação de pequenas bibliotecas de utilidades. Imagine que sua empresa pode possuir uma série de arquivos LESS, e em um determinado projeto você necessita de acesso a esses mixins, variáveis, etc. Organizar seus documentos com namespaces fácilita a visualização e localização de uma determinada instrução no seu documento LESS, como por exemplo, um mixin customizado que pode ser facilmente encontrado a partir da sua indicação de namespace.
someRule {
# > .border-radius(10px);
}
Como podemos ver, o LESS facilita uma série de tarefas que são praticamente impossíveis de serem efetuadas pelo CSS tradicional.
Aconselho a todos que tenham interesse em se aprofundar mais na biblioteca a conhecer o website (http://lesscss.org/). Lá você poderá encontrar a documentação com maior riqueza de informações também poderá ver alguns exemplos de código que não foram abordados nesse post.
Qualquer dúvida, sinta-se a vontade e envie-nos um comentário!
Abraço!
Aproveitando, tem um app bem legal para compilar seus folhas de estilo feitas em Less em CSS: http://wearekiss.com/simpless
Os pré-processadores de CSS são uma mão-na-roda! Além do LESS existe o SASS que é bastante utilizado em apps Rails. E ainda existe os “frameworks CSS”, como o Compass.
Tudo isto facilita o uso de CSS em apps web.
Mas nem tudo é flores. Como o CSS gerado é bastante diferente de seu código-fonte, debugar se tornou uma tarefa quase impossível. Por exemplo, selecionar uma área utilizando o Firebug apresentará um CSS diferente do seu, além do número da linha nunca corresponder.
Saulo,
O Compass tem um “modo de debug” que insere um comentário em cima de toda regra gerada com a linha da regra original. Acredito que esse problema pode ocorrer sim com o LESS. 😉