« HE:labs
HE:labs

Como criar um sprite responsivo

Postado por Thiago Gonzalez em 09/05/2014

Sprite é o conceito de unir várias imagens que servem uma aplicação numa mesma imagem, evitando inúmeras requisições e diminuindo o tempo de carregamento de sua página. Mas como fazer isso quando estas imagens devem ser responsivas?

Vamos imaginar o seguinte exemplo: uma lista de escudos de times. Temos 5 escudos de 64x64 e gostaríamos de uní-los para criar um sprite. Se formos pensar apenas na criação deste sprite, utilizando o tamanho original das imagens, teríamos algo como:

Sprite gerado com os 5 escudos:

Escudos

HTML:

1 <ul id="crests">
2   <li class="crest team-a"><a href="#">Team A</a></li>
3   <li class="crest team-b"><a href="#">Team B</a></li>
4   <li class="crest team-c"><a href="#">Team C</a></li>
5   <li class="crest team-d"><a href="#">Team D</a></li>
6   <li class="crest team-e"><a href="#">Team E</a></li>
7 </ul>

CSS:

 1 * {
 2   -webkit-box-sizing: border-box;
 3   -moz-box-sizing: border-box;
 4   box-sizing: border-box;
 5 }
 6 
 7 #crests {
 8   $crest-size: 64px; // Tamanho dos escudos
 9 
10   .crest {
11     float: left;
12     margin-right: 10px;
13 
14     a {
15       background-image: url('crests.png');
16       background-repeat: no-repeat;
17       display: block;
18       height: $crest-size;
19       text-indent: -9999em;
20       width: $crest-size;
21     }
22 
23     &.team-a a { background-position: ($crest-size * 0) 0 }
24     &.team-b a { background-position: ($crest-size * -1) 0 }
25     &.team-c a { background-position: ($crest-size * -2) 0 }
26     &.team-d a { background-position: ($crest-size * -3) 0 }
27     &.team-e a { background-position: ($crest-size * -4) 0 }
28   }
29 }

Veja este exemplo neste link.

Apenas isso funcionaria bem para o básico, ou seja, utilizarmos os escudos no tamanho original deles, sem pensarmos em responsivo. Imaginem que temos um breakpoint para mobile, com um valor máximo de 768px. Nossos escudos devem iniciar em 64px e ir diminuindo, dependendo da resolução do device. Os cinco escudos devem sempre ficar na mesma linha. Como faremos para exibir escudos com tamanhos diferentes, se só temos um sprite com tamanho fixo? Vejam a versão atualizada do CSS mostrado acima, já preparado para o modelo responsivo:

CSS:

 1 * {
 2   -webkit-box-sizing: border-box;
 3   -moz-box-sizing: border-box;
 4   box-sizing: border-box;
 5 }
 6 
 7 $how-many-crests: 5; // Número de colunas
 8 $crest-max-size: 64px; // Tamanho máximo dos escudos
 9 
10 #crests .crest {
11   float: left;
12   margin-right: 10px;
13 
14   a {
15     background-image: url('crests.png');
16     background-repeat: no-repeat;
17     background-size: $how-many-crests * 100%;
18     display: block;
19     height: 0;
20     padding-bottom: 100%;
21     text-indent: -9999em;
22     width: $crest-max-size;
23   }
24 
25   &.team-a a { background-position: 0 0 }
26   &.team-b a { background-position: 25% 0 }
27   &.team-c a { background-position: 50% 0 }
28   &.team-d a { background-position: 75% 0 }
29   &.team-e a { background-position: 100% 0 }
30 }
31 
32 @media screen and (max-width: 768px) {
33   #crests {
34     margin: 0 auto;
35     width: 80%;
36 
37     .crest {
38       margin: 0;
39       padding: 0 10px;
40       width: 100% / $how-many-crests;
41 
42       a {
43         margin: 0 auto;
44         max-width: 64px;
45         width: 100%;
46       }
47     }
48   }
49 }

Veja que utilizei porcentagem para posicionar cada imagem dentro do sprite e também utilizei background-size, onde 100% significa um escudo. Já que temos 5, então o valor será de 500%. O padding-bottom com valor de 100%, podemos utilizar para "imitar" a largura na altura. Como temos um valor de largura indefinido (100% sempre), a altura também se ajustará a este valor. Como a altura será baseada no padding de 100%.

Veja o resultado deste trabalho neste link.

Aumente e diminua a janela do resultado que você verá os escudos aumentando e diminuindo, de acordo com a resolução.

Infelizmente, esta solução é feita apenas para imagens quadradas. Para padrões de imagens diferentes, o trabalho é maior, que ficará para outro post.

Compartilhe

Sabia que nosso blog agora está no Medium? Confira Aqui!