CSS Sprites

Gdy łączymy się ze stroną, przeglądarka wysyła do niej żądania (HTTP request) o pobranie różnych plików – grafik, skryptów itp. Następnie otrzymuje zwrot w postaci odpowiednich danych. Tak to wygląda w największym skrócie. Im więcej takich requestów, tym logicznie nasza przeglądarka musi wysłać z domu do serwera więcej requestów, i tym samym strona ładuje się wolniej.

My jako webmasterzy powinniśmy starać się by takich połączeń było jak najmniej.

Optymalizacja liczby requestów

Przede wszystkim ograniczamy liczbę plików JS, CSS i grafik.
Te pierwsze warto pakować we wspólne biblioteki (np skrypty odpowiedzialne za obsługę formularzy wrzucamy w jeden plik). Dodatkowo kod tych skryptów możemy spakować np za pomocą http://dean.edwards.name/packer/.

Style jak to style. Ta sama technika co powyżej. Niektórzy uważają, że CSS nie muszą być czytelne – wtedy warto je spakować np za pomocą http://www.minifycss.com/css-compressor/ (takich kompresorów jest bardzo dużo – wystaczy w google wpisać „css minimizer”). Ja osobiście wolę jednak style bardziej czytelne, bo łatwiej je potem debugować. Co człowiek to inne podejście.

Oczywiście powyższe rady warto stosować z głową. Jeżeli piszę, żeby pliki js pakować we wspólne biblioteki, to nie znaczy to, że od razu koniecznie musimy wszystko spakować do jednego pliku. Tak samo w przypadku CSS. Nie jest jakimś złem używanie komendy @import. Używanie jej jest nawet całkiem dobre, bo dzięki niej można bardzo fajnie uporządkować sobie style, rozbijając je na pliki (np style do formularzy, style inputów, style layoutu itp). Pamiętajcie, żeby się nie zatracać w optymalizacji pomijając wszystko inne.

CSS Sprites

W przypadku grafiki stosuje się technikę zwaną CSS sprites. Polega ona na wrzuceniu grafik do wspólnego PNG, a następnie za pomocą CSS pobierania odpowiednich części tak przygotowanego pliku. Proste w teorii, ale jak się zaraz przekonamy proste i w praktyce.

Sprite youtube

Powyższa grafika to sprite ze strony Youtube. Ile tam mamy oddzielnych grafik? 30? 50? Ciężko nawet zliczyć. Umieszczając je wszystkie na jednej wspólnej grafice redukujemy liczbę requestów z > 50 do jednego.

My zaczniemy od nieco prostszej wersji sprita :)

Aby pobrać odpowiednie części za pomocą CSS wystarczy skorzystać z właściwości background-position.
Pobierzmy na przykład ikonę klucza. Znajduje się ona w pozycji x:137 y:12 i ma wymiary 46×46.

.wrench {
     display: inline-block;
     overflow: hidden;
     width: 46px;
     height: 46px;
     background: url(sprite.png);
     background-position: -147px -12px;
     background-repeat: no-repeat;     
}

Ujemne wartości przy pozycji tła przesuwają tło w odpowiednie miejsce. overflow:hidden sprawia, że element przycina wszystko co jest poza nim (także tło). Zresztą co ja będę wam tłumaczył. Jedna animacja zastąpi tysiąc słów:

I w zasadzie jest to cała zasada działania. Opis wszystkich ikon z zastosowaniem skróconych właściwości css wygląda tak:

.icon {
     background: url(sprite.png) no-repeat;
     overflow:hidden;
     display:inline-block;
}
.icon.red-dot {
     background-position:-12px -12px;
     width:43px;
     height:43px;
}
.icon.green-dot {
     background-position:-72px -12px;
     width:43px;
     height:43px;
}
.icon.wrench {
     background-position:-137px -12px;
     width:46px;
     height:45px;
}
.icon-alert {
     background-position:-195px -12px;
     width:46px;
     height:41px;
}

Wycinki sprita

W powyższym przykładzie mieliśmy na sztywno ustalone rozmiary naszych stylowanych obiektów. Dzięki temu overflow:hidden sprawiał, że tło poza elementem nie było wyświetlane. W wielu przypadkach szerokość elementu nie będzie znana. Spowoduje to, że jeżeli umieścimy na nim naszą ikonę, tuż obok niej pojawi się dalsza część sprita czyli inne ikony. Jednym słowem lipa.

Aby móc pobierać tylko dany fragment sprita, skorzystamy z metody background-clip, która dobrze jest opisana tutaj. Niestety nie działa ona na starszych przeglądarkach z IE8 włącznie, dlatego poniżej pokażę wam też inne sposoby.

Jednym z rozwiązań tego problemu jest ułożenie grafik na spricie jedna pod drugą. To samo tyczy się teł, które będą powtarzane w poziomie.

Element :before, :after dla spritów

Jest jeszcze inna technika, aby obejść powyższą niedogodność. Wystarczy skorzystać z selektorów :before lub :after, dzięki którym możemy wstawiać do dokumentu pseudo elementy. Takie pseudo cudaki możemy ostylować tak samo jak w powyższym przykładzie:

.icon-button {
     position: relative;
}

.icon-button:before {
     content:'';
     display:block;
     background: url(http://domanart.pl/wp-content/uploads/2012/08/sprite1.png) -195px -12px no-repeat;
     overflow:hidden;
     width:46px;
     height:41px;
     position:absolute;
     top:5px;
     left:5px;
}

http://jsfiddle.net/kartofelek007/Ryj5u/

Pseudo element wstawiony za pomocą :before pozycjonujemy absolutnie względem jego „rodzica”, który ma pozycjonowanie relatywne (chociaż w tym przypadku ciężko mówić o rodzicu, bo elementy before i after to takie bękarty html – w końcu to shadow dom).
Musimy mu też nadać tryb wyświetlania block. Reszta stylowania jest taka sama jak w poprzednich przykładach. Przy właściwości content: lepiej używać apostrofów podwójnych, niż pojedynczych. Zauważyłem, że IE zupełnie głupiał przy pojedynczych (chociaż ogólnie starsze IE z pseudo elementami nie za bardzo się lubią, więc cała ta technika nie za bardzo pasuje dla starych IE).
Najpiękniejsze w tej metodzie jest to, że taki pseudo element możemy „obrabiać” tak samo jak każdy element na stronie. Możemy mu przesuwać tło, przemieszczać (top, left), skalować, obracać, czy stosować inne transformacje css. W poniższym przykładzie ikonkę obróciłem do góry nogami (chociaż tak właściwie to ona nie ma nóg…)

http://jsfiddle.net/kartofelek007/7H3nd/

Tworzenie spritów

Sprity zazwyczaj tworzymy w naszym ulubionym programie graficznym :)
W Photoshopie najlepiej użyć do tego narzędzia slice.

.

Za jego pomocą wyznaczamy kolejne części sprajta.

Następnie za pomocą narzędzia slice select (patrz poprzednia grafika) możemy 2x kliknąć w któryś z wyznaczonych obszarów, aby w okienku, które się ukaże zobaczyć podane wymiary i położenie danego obszaru (oczywiście x i y przestawiamy na ujemne).

Jest to duże ułatwienie w porównaniu z używaniem standardowego zaznaczania i panelu info w Photoshopie (ileż ja się nakląłem używając tej standardowej metody).

Inne narzędzia

Ale, ale. Tworzenie spritów w programach graficznych nie jest ani super przyjemne, ani wygodne.
Dlatego też powstało sporo narzędzi przeznaczonych do tego celu.

Wśród internetowych aplikacji warto zwrócić uwagę na:

Wśród aplikacji na komputer jedną z lepszych jest http://spriterightapp.com/, niestety przeznaczony tylko dla ludzi miłujących się w jabłkach.

Dla zwykłych śmiertelników też coś można wygrzebać. Osobiście polecam zapoznać się z dwoma aplikacjami:
http://www.jonathanrowny.com/journal/sprite-hero-yet-another-css-sprite-generator oraz http://collamo.jp/?page_id=95. Każda z nich ma swoje plusy i minusy, dlatego warto przetestować obie.

Dodatkowe informacje na temat spritów znajdziecie na http://coding.smashingmagazine.com/2012/04/11/css-sprites-revisited/.

Jeżeli macie jakieś pytania, zapraszam do komentowania :)

Komentarze