Recursos do LESS que você provavelmente não conhece

Neste post vamos analisar algumas das novas funcionalidades presentes no LESS e como estas podem tornar nosso workflow mais prático e simples.

Já faz algum tempo desde nosso ultimo contato com o LESS. Na ultima vez, conversamos como a tecnologia caminhava em 2013, quando o LESS estava na versão 1.2.0. Enquanto escrevo este artigo, o LESS está quase na versão 2.0, e uma série de melhorias e recursos foram implementados em cada versão da solução.

Neste post, vamos analisar estes recursos e já podemos adiantar que alguns são realmente muito úteis.

Este post faz parte do projeto que participo de tradução dos artigos dos blogs da Envato, Webdesigntuts+, Gamedevelopmenttuts+ e Nettuts+. Todos os direitos reservados para Envato.

Link para artigo original: A Few Things You Might Not Know About LESS
Autor do artigo original: Thoriq Firdaus
Link da Envato para o artigo traduzido: Alguns recursos do LESS que você provavelmente não conhece


Estendendo/Extend seletores

Para começar, vamos falar sobre extend. O Extend foi o recurso mais requisitado, já que os concorrentes Sass e Stylus já utilizam a algum tempo. A utilização do método extend nos permite criar um output do código CSS agrupando o seletores que compartilham as mesmas Mixins. Isso ajuda a manter o código limpo (DRY) e reduz muito o tamanho do arquivo.

No Sass, assim como no Stylus, nós utilizamos a diretiva @extend para estender um mixin. Com o LESS é diferente; Ele utiliza uma pseudo-clas proprietaria, :extend(), e eu acho que utilizar uma pseudo-class ao invés de uma diretiva @ é uma escolha inteligente.

Uma pseudo-class dentro dos padrões CSS permite aplicar novos regras de estilo para um seletor existente sem reescrever os estilos declarados. O :extend() também utiliza um método similar, incluindo novos estilos em uma regra já criada.

Vamos supor que temos uma mixin para gerar a forma de um círculo, como no exemplo:

.circle {
  border-radius: 50%;
}

Podemos utilizar a pseudo-class :extend() para utilizar o estilo da classe .circle com outros seletores, como no exemplo:

.circle {
  border-radius: 50%;
}

.button:extend(.circle) {
  position: absolute;
  top: 0;
  left: 0;
}

Você também pode declarar a pseudo-class :extend() com o símbolo &.

.circle {
  border-radius: 50%;
}

.button {
  &:extend(.circle);
  position: absolute;
  top: 0;
  left: 0;
}

Esse exemplo vai declarar dois seletores .button; o primeiro vai enquadrar a classe .circle, e depois compartilhar o mesmo border-radius:

.circle,
.button {
    border-radius: 50%;
}

.button {
    position: absolute;
    top: 0;
    left: 0;
}


Múltiplos Mixins

Você pode estender múltiplos mixins com um único seletor. No Sass e no Stylys, nós precisamos declarar cada mixin com uma diretiva @extend separada, enquanto no LESS nós declaramos as mixins em um único seletor :extend() separando cada um deles com uma vírgula. Seguindo o exemplo anterior, vamos precisar de outro seletor para definir a cor padrão do círculo, como no exemplo abaixo:

@gray: #ccc;
@gray-lighter: #f3f3f3;
.circle {
  border-radius: 50%;
}

.circle-default {
  background-color: @gray-lighter;
  border: 1px solid @gray;
}

.button {
  &:extend(.circle, .circle-default);
  position: absolute;
  top: 0;
  left: 0;
}

Que vai ser compilado para:

.circle,
.button {
  border-radius: 50%;
}

.circle-default,
.button {
  background-color: #f3f3f3;
  border: 1px solid #cccccc;
}

.button {
  position: absolute;
  top: 0;
  left: 0;
}

Note que os seletores que compartilham os mesmos estilos das mixins são declarados de acordo.


Estendendo seletores combinados

Outra coisa que você deve saber sobre o método extend do LESS é que ele estende apenas os estilos do primeiro seletor. Estilos empregados a itens filhos ou seletores combinados não serão afetados. Como a classe .button no exemplo abaixo:

@gray: #ccc;
@gray-lighter: #f3f3f3;
.parent {
    color: @gray;
    .child {
        color: @gray-lighter;  
    }
}
.button:extend(.parent) {
    font-family: Arial;
}

Não vai herdar os estilos do seletor .child:

.parent,
.button {
  color: #cccccc;
}
.parent .child {
  color: #f3f3f3;
}
.button {
  font-family: Arial;
}

Se você deseja que a classe .button compartilhe os estilos da classe .child, você precisa sinalizar ao LESS incluindo o seletor com parênteses, conforme o exemplo abaixo:

.button:extend(.parent .child) {
    font-family: Arial;
}

Neste exemplo, o resultado seria:

.parent,
.button {
  color: #cccccc;
}

.parent .child,
.button {
  color: #f3f3f3;
}

.button {
  font-family: Arial;
}

Pessoalmente, eu curto como o LESS encara o metódo extend. Da mais controle ao escolher qual seletor deve entrar no mixin. Planeje como vai construir os estilos do seu website e se houver a necessidade de compartilhar algum estilo, você pode optar por utilizar o método extend.

Placeholder

Usuários do Sass já devem conhecer o seletor placeholder. Um placeholder é similar a uma class ou um ID, e contém um conjunto de propriedades e declarações e é utilizado em conjunto com a diretiva @extend. Um placeholder é declarado com um sinal % e nunca é compilado para CSS. Então, quando um código como o do exemplo abaixo é executado:

%rounded {
  border-radius: 30px
}
.button-default {
  @extend %rounded;
}

…o output será:

.button-default {
  border-radius: 30px;
}

O LESS não possui um seletor especial como este, mas, você pode criar o mesmo efeito no arquivo output adicionando () no fim do seletor. Por exemplo:

.rounded() {
  border-radius: 30px
}
.button-default {
  .rounded;
}

Esse método, no LESS, é conhecido oficialmente como Mixins como Functions.

Mais opções de importação

O LESS conta com algumas opções para importar arquivos de estilo. Uma das minhas favoritas é a opção de (reference). Essa opção configura o LESS para não compilar o arquivo de estilo junto com o arquivo de estilo importado. O LESS vai tratar este arquivo de estilo apenas como uma referência. Vamos dar uma olhada no nosso primeiro exemplo novamente:

Aqui temos estilos básicos para criar um círculo. Desta vez, nos salvamos os estilo em um arquivo mixin separado, mixins.less.

@gray: #ccc;
@gray-lighter: #f3f3f3;
.circle {
  border-radius: 50%;
}
.circle-default {
  background-color: @gray-lighter;
  border: 1px solid @gray;
}

Agora nós importamos o arquivo mixins.less no nosso arquivo de estilo utilizando o comando (reference).

@import (reference) "mixins.less";

Agora podemos utilizar as Mixins no arquivo de estilo, como no exemplo abaixo:

.button {
  .circle;
  .circle-default;
  position: absolute;
  top: 0;
  left: 0;
}

Como mencionado, as mixins do arquivo mixins.less não vão ser compiladas para o arquivo de estilo padrão. Ao invés, o output vai apresentar apenas o seletor .button:

.button {
  border-radius: 50%;
  background-color: #f3f3f3;
  border: 1px solid #cccccc;
  position: absolute;
  top: 0;
  left: 0;
}

Acho essa opção muito útil principalmente quando utilizada com frameworks como o Bootstrap.

@import (reference) "less/bootstrap/bootstrap.less";

No exemplo acima, permitimos a utilização de estilos, mixins e function do Bootstrap em qualquer arquivo de estilo, sem ter de usar todo aquele código presente nos arquivos do Bootstrap.

Convertendo CSS para LESS

Outra opção que acho super útil é a (less). As vezes incorporamos bibliotecas como a vanilla .css dessa forma:

@import "library.css";

No exemplo acima. o LESS vai tratar o arquivo como CSS puro. Isso significa que o arquivo de estilo não vai ser compilado, e o output vai continuar da mesma forma, apenas com a linha @import "library.css";, e todas as classes e seletores não vão estar disponíveis como as mixins, por exemplo; você não vai conseguir estender ou reutilizar os seletores.

Se você quiser manipular o output como um arquivo LESS, você precisa adicionar a opção (less) após o @import do arquivo.

@import (less) "library.css";

Agora, se a intenção é apenas criar uma referência, importe o arquivo com a combinação de referências (less) e (reference):

@import (less,reference) "library.css";

Interpolando variáveis

Hugo Giraudel, em um de seus tutoriais para o Tuts+, explicou o que, porque e como funciona a interpolação de variáveis no Sass. O LESS utiliza o comando @{} para interpolar variáveis, colocando o nome da variável entre parênteses, como no exemplo:

@variable: 'value';
@{variable} //Interpolada

Nós podemos utilizar uma variável dessa maneira quantas vezes quisermos. As vezes utilizo essa técnica para especificar o caminho de arquivos de imagens e fontes:

@path-img: 'assets/img';
.header {
  background-image: url('@{path-img}/bg.png');
}

Você também pode incluir a interpolação com o comando @import, o que não é possível com Sass.

// Variáveis
@path-less: 'src/less';
@path-img: 'assets/img';
 
// Arquivo de estilo externo
@import '@{path-less}/mixins.less';
 
// Estilos
.header {
  background-image: url('@{path-img}/bg.png');
}

Ou, dependendo do caso, utilizar apenas para declarar seletores e propriedades:

@name: color;
.default-@{property} {
  @{property}: #0ee;
  background-@{property}: #999;
}

Como você pode notar, o uso e a aplicação de variáveis interpoladas no LESS é bastante flexível.

Fusão de propriedades

A ultima novidade do LESS que vamos explorar é a merging, ou fusão. A fusão facilita a forma como lidamos com propriedades CSS de múltiplos valores, como por exemplo text-shadow, box-shadow, e transition.

Vamos supor que você quer aplicar um efeito de transição na cor de um botão e na cor de fundo. Temos uma mixin com a declaração da transition para a cor do texto.

.color-transition {
  transition: color 350ms;
}

Agora vamos incluir este com outra regra de estilo com uma transition já declarada:

.button {
  .color-transition;
  transition: background-color 300ms;
}

Neste caso vamos terminar com duas declarações de transition em uma unica regra de estilo:

.button {
  transition: color 350ms;
  transition: background-color 300ms;
}

O efeito de transição para a color não funciona, pois a ultima propriedade transition vai subscrever a primeira. Para fazer com que as duas transições operem, você precisa declarar os valores em uma unica declaração transition, demarcando cada um com uma vírgula. É nesta hora que o recurso de fusão entra em cena.

Adicione um sinal de mais (+) após cada propriedade, conforme o exemplo:

.color-transition() {
  transition+: color 350ms;
}

.button {
  .color-transition;
  transition+: background-color 300ms;
}

Agora temos o seguinte resultado no arquivo output compilado:

.button {
  transition: color 350ms, background-color 300ms;
}


Conclusão

Creio que esses recursos — estender, mixins como function/funcões, interpolação de variáveis, opções de importação, e fusão/merge — são melhorias muito significantes para o LESS. Esses recursos de fato nos ajuda a produzir mais com mais eficiência e facilidade.