Compass Sprites como marcadores de posição

[EDIT] Uma solução melhor seria adicionar esta opção ao núcleo da Compass. Criei uma solicitação pull para isso em https://github.com/chriseppstein/compass/pull/1448


O que saber antes de ler

Para entender totalmente este tutorial, você deve estar familiarizado com os conceitos de geração de sprites de bússola e importações mágicas. Para ler mais sobre isso, consulte o guia Spriting with Compass e as seções listadas nessa página.

Além disso, será bom ter algum conhecimento dos marcadores de posição do Sass. Para isso, há um ótimo artigo também sobre Estendendo seletores de espaço reservado com Sass .

O problema

Por padrão, o uso de importações mágicas de compasso para sprites gerará seletores de classe, que podem ser estendidos para aplicar a imagem de fundo a outro seletor.

O problema geralmente é que você tem um arquivo importando todos os sprites, e esse arquivo, toda vez que for importado, criará algum CSS de saída que você pode ou não usar.

Para resolver este problema, deve haver uma maneira de importar seletores de sprite como marcadores de posição, de forma que nenhum seletor de estilo seja gerado a menos que você realmente os estenda.

Há um problema no Compass que detalha esse problema.

Solução

Para tornar a solução abaixo mais fácil de entender, vamos usar como exemplo a criação e importação de um sprite “ícones”.

1) Definir seletores de base

O Compass permite que você altere o seletor de base para cada sprite importado. Mudar isso fará com que o seletor de sprite principal para um sprite seja o que você quiser: até mesmo um espaço reservado. A única coisa que teríamos que fazer, em nosso exemplo, é:

$icons-sprite-base-class: "%icons-sprite"

2) Importar e compilar imagens:

Agora, podemos importar nossas imagens de sprite.

@import "icons/*.png"

É quando o Compass cria um parcial “mágico” do Sass, contendo não apenas os seletores, mas também os mixins para fazer uso da funcionalidade do sprite. Normalmente, fazendo apenas essa importação, já haveria um seletor de saída, que em nosso caso seria “.icons-sprite”. Como mudamos antes, não haverá saída.

3) Incluir mixin de sprite personalizado

Como expliquei na etapa acima, a importação das imagens do sprite fará com que alguns mixins sejam gerados. Dentre esses mixins, Compass importa o “compass / utilities / sprites / base”, que define um mixin de “sprites”. Esse mixin é nosso problema, pois ele é responsável por criar nossos seletores de sprite, mas ao contrário do que fizemos na etapa 1, não podemos interagir com ele para alterar como ele cria os seletores. Simplesmente usa um seletor de classe por padrão. Mas o que podemos fazer é sobrescrever este mixin para atender às nossas necessidades. Então, neste ponto, vamos adicionar nosso mixin personalizado conforme abaixo:

=sprites($map, $sprite-names, $base-class: false, $dimensions: false, $prefix: sprite-map-name($map), $offset-x: 0, $offset-y: 0)
@each $sprite-name in $sprite-names
@if sprite_does_not_have_parent($map, $sprite-name)
$full
-sprite-name: "#{$prefix}-#{$sprite-name}"
%#{$full-sprite-name}
@if $base-class
@extend #{$base-class}
+sprite($map, $sprite-name, $dimensions, $offset-x, $offset-y)

Visite http://compass-style.org/reference/compass/utilities/sprites/base/#mixin-sprites para ver a versão padrão deste mixin.

4) Incluir sprites

Finalmente, faríamos como de costume e incluiríamos nossos sprites.

+all-icons-sprites(true)

Tenha em mente que esta é apenas uma das muitas maneiras de usar os sprites da bússola, e que as etapas 3 e 4 são necessárias apenas para esta forma específica. Na minha opinião essa é a melhor forma de usar sprites já que, por enquanto, eu só teria que usar extends para fazer uso dele, e não mixins; o que manterá minha saída de CSS menor. Siga a etapa 5 para obter mais instruções.

5) Uso com @extend

Então, agora você tem todos os sprites “compilados” como seletor de espaço reservado; você não os verá enviados para o CSS, obviamente, porque o placeholder não será gerado a menos que sejam estendidos. A regra de nomenclatura desses seletores de espaço reservado segue a mesma que seria usada com o seletor de classe ( ), apenas com um precedente no lugar do usual . Digamos que temos uma imagem chamada “fechar” no sprite dos ícones, ela seria estendida da seguinte forma:%[DIRECTORY]-[IMAGE]%.

.foo
@extend %icons-close

Pronto para usar

Aqui está o código Sass final pronto para usar para fazer os sprites serem produzidos como marcadores de posição:

// Step 1.
$icons
-sprite-base-class: "%icons-sprite"

// Step 2.
@ import "icons/*.png"

// Step 3.
=sprites($map, $sprite-names, $base-class: false, $dimensions: false, $prefix: sprite-map-name($map), $offset-x: 0, $offset-y: 0)
@each $sprite-name in $sprite-names
@if sprite_does_not_have_parent($map, $sprite-name)
$full
-sprite-name: "#{$prefix}-#{$sprite-name}"
%#{$full-sprite-name}
@if $base-class
@extend #{$base-class}
+sprite($map, $sprite-name, $dimensions, $offset-x, $offset-y)

// Step 4.
+all-icons-sprites(true)

// Step 5. (usage)
div

@extend %icons-IMAGE_NAME

Observe o espaço adicional entre @e após a etapa 2; Coderwall insiste em transformá-lo em uma menção se eu remover o espaço.import "icons/*.png"

Para cada novo sprite, você terá que repetir os passos 1, 2, 4 e 5 deste tutorial. A terceira etapa, porém, pode permanecer a mesma.

Conclusão

Esta solução não é uma resposta definitiva para este problema, pois depende da substituição dos mixins do Compass; o que pode causar problemas nas novas versões do framework. No entanto, isso nos dá uma maneira de aproveitar sprites Compass hoje sem bagunçar muito nossos arquivos CSS de saída.

Eu ficaria feliz em ouvir sua opinião sobre esta solução!