Para finalizar esta série sobre o mjamado.com, falta falar sobre o que é, para mim, a tecnologia mais útil que aprendi no último ano: SASS, um superset da linguagem CSS, juntamente com Compass, uma biblioteca de mixins para usar com SASS (mixins é o termo convencionado para referir o que não são mais que pequenas funções).
Não vou alongar-me sobre todas as vantagens do SASS (estão aí os links, é dar uma voltinha), mas vou focar quatro pontos que me são caros.
Isto tem sido pedido à W3C inúmeras vezes, e que falta faz à especificação CSS. Uma das maiores dores de manutenção é precisamente mudar o esquema de cores, ou tamanhos das fontes; era óptimo poder definir-se este tipo de coisas numa variável. Ainda bem que o SASS suporta:
$baseColor: #349AFF;
$lightBaseColor: #4DA7FF;
$darkBaseColor: #1363B2;
body
{
background-color: $baseColor;
color: $darkBaseColor;
}
.highlight
{
background-color: $lightBaseColor;
color: $baseColor;
}
O CSS3 trouxe a função calc(), que não serve exactamente a mesma coisa, mas veio colmatar outra lacuna há muito pedida por webdesigners, a capacidade de atribuir valores provenientes duma expressão. No entanto, a função calc() serve apenas para valores válidos (o CSS não tem variáveis, certo?) – não tem o uso que poderia ter como facilitadora de desenvolvimento; deixando de lado, claro, que o suporte é muito fraco (nem o Opera, nem o Safari suportam) e que coloca alguns problemas de performance no renderer dos browsers.
O uso das expressões e funções, no SASS, está intimamente ligado à capacidade de serem usadas variáveis. Um exemplo seria a manutenção de proporções ao nível do tamanho de letra (no exemplo abaixo, é usada a proporção áurea):
$baseFontSize: 12px;
$phi: 1.618;
$phi2: $phi*$phi;
$phi3: $phi2*$phi;
p, h6 { font-size: $baseFontSize; }
h5 { font-size: round($baseFontSize*$phi); }
h4 { font-size: round($baseFontSize*$phi2); }
h3 { font-size: round($baseFontSize*$phi3); }
h2 { font-size: round($baseFontSize*$phi2*$phi2); }
h1 { font-size: round($baseFontSize*$phi3*$phi2); }
Mixins são funções definidas por nós, prontas a usar no estilo que nos aprover. Podendo aceitar parâmetros, as aplicações são ilimitadas. Por exemplo, vamos construir um gradiente cross-browser pronto a usar em vários sítios:
@mixin gradienteLinear($cor1, $cor2)
{
/* Firefox 3.6+ */
background: -moz-linear-gradient(top, $cor1, $cor2);
/* Chrome, Safari 4+ */
background: -webkit-gradient(
linear, top, bottom, color-stop(0%, $cor1), color-stop(100%, $cor2)
);
/* Chrome 10+, Safari 5.1+ */
background: -webkit-linear-gradient(top, $cor1, $cor2);
/* Opera 11.10+ */
background: -o-linear-gradient(top, $cor1, $cor2);
/* Internet Explorer 10+ */
background: -ms-linear-gradient(top, $cor1, $cor2);
/* standard */
background: linear-gradient(top, $cor1, $cor2);
/* Internet Explorer 6+ */
filter: progid:DXImageTransform.Microsoft.gradient(
startColorstr='$cor1', endColorstr='$cor2', GradientType=0
);
}
.btn
{
@include gradienteLinear(#AAA, #CCC);
}
Na linha 1 defino o mixin; dentro, tenho todas as declarações necessárias. Depois, na linha 21, incluo esse mixin numa classe. A CSS resultante terá as declarações dentro da classe. Embora não reduza o tamanho do CSS resultante (o melhor que o tradutor fará será retirar comentários, espaçamentos e quebras de linha desnecessárias), reduz consideravelmente a complexidade de desenvolvimento.
Claro que este exemplo concreto foi propositado...

Como disse no início, o SASS tem um projecto intimamente ligado, o Compass, uma biblioteca de mixins – os autores definem-no como uma plataforma de desenvolvimento CSS, mas, embora tenha algumas ferramentas iniciais úteis (é possível começar-se a partir duma base Blueprint ou 960 Grid, por exemplo), é basicamente um repositório de mixins.
Uma voltinha pela referência oficial fará saltar à vista imensos mixins úteis para atalhar trabalho, sobretudo em áreas onde é preciso especificar os vários prefixos dos browsers. O exemplo acima poderia ser reescrito, usando Compass, da seguinte forma:
@import "compass/css3/images"
.btn
{
@include background-image(linear-gradient(top, #AAA, #CCC));
}
Na primeira linha é importada a biblioteca do Compass que contém os mixins desejados, e, na classe, é só incluir o mixin concreto. Mais simples não podia ser.
De notar que este mixin em particular não inclui a declaração específica do Internet Explorer 9 e inferiores (via filter). Os criadores do Compass são defensores convictos que as especificidades do Internet Explorer devem ser tratadas por estilos condicionais, e visto que a declaração filter não é, nem de perto, nem de longe, a mesma coisa que os gradientes tradicionais, é incluída com um mixin à parte (no caso, o mixin filter-gradient()). Sobre estilos condicionais falarei no próximo ponto.
Tal como no exemplo acima é importada uma biblioteca específica do Compass, também é possível incluir as nossas próprias bibliotecas ou, no caso mais comum, folhas de estilo parciais. O único requisito é que os nomes dos ficheiros comecem por um underscore (_); tudo o que está lá dentro pode ser SCSS válido. Por exemplo, eu tenho sempre um ficheiro _base.scss com mais ou menos o seguinte:
@import "compass/reset";
@import "compass/layout/sticky-footer";
@import "compass/typography/vertical_rhythm";
@import "compass/css3/images";
@import "compass/css3/border-radius";
@import "compass/css3/transition";
@import "compass/css3/transform";
@import "compass/css3/text-shadow";
@import "compass/css3/box-sizing";
$base-font-size: 14px;
$base-line-height: 21px;
$lineHeight: 1.5em;
$fontFamily: 'Cantata One', Georgia, serif;
$alternativeFontFamily: 'Imprima', Verdana, Helvetica, sans-serif;
$normalFontColor: #222;
$baseColor: #E49818;
$lightBaseColor: #FFB334;
$darkBaseColor: #976208;
$lightComplement: #187FE4;
$darkComplement: #004C97;
@include establish-baseline;
@include sticky-footer(54px, "#content", "#footerExpander", "#footer");
* { @include box-sizing("border-box"); }
i,em { font-style: italic; }
b,strong { font-weight: bold; }
Depois, no meu ficheiro principal, é só importar este ficheiro, sem underscore e sem extensão:
@import "base";
O interpretador do SASS incluirá todo aquele código incluído para a CSS correspondente. Alguns casos óbvios para separação são estilos de formulário, estilos de componentes relativamente complexos (calendários salta logo à vista), estilos específicos para dispositivos de dimensões reduzidas e estilos para IE.
Estes últimos dois casos, para além da separação, requerem outro tipo de código. As media queries são comumente usadas directamente nas tags link, assim:
<link rel="stylesheet" media="screen and and (max-width: 1024px)" href="tablets.css" />
No entanto, podem ser usadas dentro das próprias folhas de estilo:
@media screen and (max-width: 1024px)
{
/* estilos para tablets */
}
@media screen and (max-width: 820px)
{
/* estilos para smartphones grandes */
}
Juntando isto com a capacidade de importação do SASS, podemos ter um ou mais ficheiros relativos a media queries, tendo apenas o cuidado de os importar no final do ficheiro principal, fazendo com que os estilos sejam herdados correctamente.
A principal vantagem desta técnica é servir apenas um ficheiro, poupando nos requests – infelizmente, usando as tags link, os browsers fazem o download de todas as folhas de estilo, apesar de não cumprirem com a media query. Facilmente se chega a quatro ou cinco requests de CSS, mais uma ou duas caso o browser seja um dos IE.
Esse caso dos IE é ligeiramente mais complicado. O método habitual de incluir folhas de estilo condicionadas a certas versões do IE é usando comentários condicionais, uma especificidade dos IE – neste caso, ainda bem que existe essa especificidade.
O exemplo acima incluiria uma folha de estilos específica quando o browser fosse o Internet Explorer 9 ou inferior (a expressão lte significa less than or equal). Infelizmente, e ao contrário das media queries, é impossível usar este tipo de condições directamente dentro da CSS. Normalmente, isso não representa um problema por aí além. O excesso de requests afectaria cerca de 60% dos utilizadores num site típico, menos (e até muito menos) noutros sites, dependendo do público-alvo. Pessoalmente, estava disposto a assumir essa penalização na esmagadora maioria dos casos, até como dissuassor do uso de browsers foleiros...
Recentemente, tropecei numa técnica para colmatar este pequeno problema; algo tão simples, que só apetece dar o belo do facepalm e exclamar "como é que ninguém tinha pensado nisto antes".
Os comentários condicionais servem para qualquer elemento; isto nem sequer é grande novidade, numa altura ou noutra todos temos usado essa técnica para desenhar alertas específicos para utilizadores do IE (eu até usei essa técnica durante algum tempo aqui no DreamsInCode):
O truque é usar comentários condicionais separados para a abertura e fecho de contentores específicos para cada IE que quisermos apanhar em particular. Só é preciso especial cuidado para que a expressão condicional seja rigorosamente a mesma, para não desbalancear as tags:
<body>
<!--[if lte IE 9]><div id="ielte9"><![endif]-->
<!--[if lte IE 8]><div id="ielte8"><![endif]-->
<!-- Conteúdo normal do site -->
<!--[if lte IE 8]></div><![endif]-->
<!--[if lte IE 9]></div><![endif]-->
</body>
O Internet Explorer 9 verá a div com o id ielte9, o IE8 verá essa e ainda a ielte8 e os browsers de outros podutores não verão nenhuma delas. Depois, na CSS, é tão simples como declarar estilos especificados com o id:
.menu
{
/* formatação normal do menu */
}
#ielte9 .menu
{
/* formatação do menu para IE9 e inferiores */
}
#ielte8 .menu
{
/* ainda qualquer coisa mais específica para IE8 e inferiores */
}
Mais uma vez, juntando a esta técnica a capacidade de importação do SASS, podemos ficar com um sistema de vários ficheiros, muito fácil de manter, sem a penalização de vários requests.
A facilidade de uso e manutenção é, aliás, o que de melhor se pode retirar do SASS, sobretudo se for conjugado com o Compass. E isso é tudo o que um webdeveloper pode pedir ao optar por uma tecnologia: menos trabalho de sapa, para se poder concentrar nas grandes opções.