Sprite SVG

<svg>
    <symbol id="icon-envelope" viewBox="0 0 22 16">
        <path
            style="fill:none;stroke:#ffa3ea;stroke-width:1"
            d="M 18,2.5 h -16.5 l 10,8 10,-8 v 12 h -20 v -8"></path>
    </symbol>
</svg>

SVG, skalowalna grafika wektorowa, to dojrzała technologia. Żyje w Sieci od dawna, jest dobrze implementowana w przeglądarkach i szeroko używana w Internecie. Zdjęcia są jedynym typem obrazu, którego nie można zastąpić SVG – tak mi się wydaję. Popatrzymy, czy można ją bezpiecznie zastąpić sprite'ów rastrowych.

Czym różną się prite SVG

Sprite pozwalają zmniejszyć liczbę żądań HTTP dla elementów graficznych, gdy wszystkie są zawarte w pojedynczym pliku, a pożądany element jest pokazywany poprzez pozycjonowanie przy użyciu CSS tego pojedynczego pliku w okienku o ograniczonym rozmiarze. Sprite SVG, ściśle mówiąc, są nazywane tak tylko warunkowo – dlatego że są pracują inaczej. Elementy graficzne są 1) zadeklarowane w węźle drzewa DOM i 2) wywoływane we właściwym miejscu. Rozważ przykład pobrany z etykiet sieci społecznościowych u dołu strony.

Teraz szczególnie o punkcie 1)

Definiowanie szablonów

Podaję niżej odpowiedny fragment kodu SVG.

Definiowanie szablonów
<svg style="display:none">
    <symbol id="icon-fb" viewBox="0 0 16 16">
        <path
            style="stroke-width:1;fill:none;[...]"
            d="M 1.327921,0.5 C 0.8706167,0.5 0.5,0.8705 [...] z"></path>
    </symbol>
    <symbol id="icon-tw" viewBox="0 0 16 16">
        <path
            style="stroke-width:1;fill:none;[...]"
            d="m 11.546616,8.0162225 c 0.499719,0 0.929144 [...] z"></path>
    </symbol>
</svg>

Liczba żądań HTTP jest zredukowana do 0 (zera), ponieważ element jest wbudowany bezpośrednio w drzewo dokumenta. Chcę się podkreslić tą drugą zaletę w stosunku do sprite'ów rastrowych (pierwsza z nich to oczywiście skalowalność). Tak, wiem, że można wmurować grafiki rastrowe do HTML również za pomocą Data-URI. Ale powtórne wykorzystanie tego elementu nie jest możliewe, stąd przydatne dla spraitów tylko w wypadku, gdy mamy mało takich elementów na stronie.

Między innym, nie wolno zapomnieć style="display: none", inaczej element SVG zajmie domyślną powirzchnie na stronie, chociaż i nic nie narysuje w niej, dlatego że <symbol> nie jest renderowany. Atrybut [id] jest wymagany, gdy chcesz wezwać tą grafikę później w dokumencie.

Odwoływanie się do szablonu

Wykorzystanie grafiki zdefiniowanej przez element <symbol>:

Używanie zdefiniowanych szablonów
<svg>
    <use href="#icon-fb" xlink:href="#icon-fb"></use>
</svg>

Element <use> odwołuje się do odpowiednego szablonu <symbol> za pomocą atrybutu href.

<symbol> vs <defs>

Kiedy przeszukasz Sieć na temat spritów SVG, znajdziesz dwa sposoby zdefiniowania szblonów: za pomocą <symbol> oraz <defs>. Uważam, że ci faceci, którzy promują drugi sposób, stosują się do tej porady, znajdującej się na połączonej powyżej stronie MDN:

Zaleca się, aby wszędzie gdzie to jest możliwo definiować elementy, do których się odnosimy, w elemencie <defs>.

I ten sposób pracuje – sprawdzałem. Ale używam pierwszego, ponieważ został on zaprojektowany specjalnie dla naszego celu:

Element <symbol> służy do definiowania szablonów graficznych obiektów, które mogą być tworzone przez element <use>. Użycie elementów <symbol> dla grafiki, która jest używana wiele razy w tym samym dokumencie, dodaje strukturę i semantykę.

Jeszcze do tego <symbol> wspiera dwa przydatne atrybuty z ekspresyjnymi nazwami: preserveAspectRatio oraz viewBox.

Jeszcze widziałem takie połączenie:

<svg style="display:none">
    <defs>
        <symbol id="icon-fb" viewBox="0 0 16 16">
            <path
                style="stroke-width:1;fill:none;[...]"
                d="M 1.327921,0.5 C 0.8706167,0.5 0.5,0.8705 [...] z"></path>
        </symbol>
        <symbol id="icon-tw" viewBox="0 0 16 16">
            <path
                style="stroke-width:1;fill:none;[...]"
                d="m 11.546616,8.0162225 c 0.499719,0 0.929144 [...] z"></path>
        </symbol>
    </defs>
</svg>

Ale nie znalazłem na to podstawy z tego co widziałem w dokumentach o SVG.

Podsumowanie

Zalety

Reasumując, nie widzę powodów używania rastrowych sprite'ów zamiast SVG. Zakładam, że nie kodujesz dla IE < 9. Kodujesz? Och, kochanie, moje współczucie... Dla reszty z nas mamy:

  1. skalowalne obrazy dla najwyższej jakości niezależnie od rozdzielczości ekranu
  2. zerowa liczba dodatkowych żądań HTTP

Do tej pory rozpatrzywaliśmy tylko zalety. Może znajdziemy jakieś wady lub ograniczenia?

Ograniczenia

Uwielbiam SVG nie tylko za skalowalność, ale także za możliwość interwencji w drzewo DOM za pomocą Javascript i animowanie tych manipulacji. Widziałeś, animację przycisku menu?#1

Zróbmy coś podobnego do naszych ikon sieci społecznościowych... Czekaj... Może zły selektor CSS czy coś takiego... Nie. Nie działa :(

Dlaczego? Ma to dobry powód. Kiedy wykorzystasz w tegu <use> jakiś <symbol> nie możesz go zmieniać. Oznacza to, że reprodukowane kopie nie powinny być uważane za niezależne elementy, a raczej za lustrzane odbicia elementu originalnego. Nie masz dostępu do elementów drzewa za pomocą CSS ani JS i żadne zdarzenie z elementem nie ma wpływu na jego szablon. Serio, jak wyobrażałem sobie manipulowanie poddrzewem szablonu, nie oczekując tych zmian w każdej z refleksji? OK, trzeba to po prostu zaakceptować. Jeśli potrzebujesz manipulować DOM SVG, musisz mieć oddzielny węzeł SVG.

Chociaż jest to zdecydowanie ograniczenie, to tylko w porównaniu do osobnego węzła SVG, a nie grafiki rastrowej. W porównaniu do rastrów, granice są tylko rozszerzone.

Jeśli masz jakieś pytania, sugestię, proszę o kontakt.

Dziękuję za przeczytanie!

#1 Animację można zobaczyć w Chrome. FF Nightly animowal atrybut d elementu <path>, ale zmienił to zachowanie później.