Skip to content

Ikony SVG w WordPress - dlaczego inline to antywzorzec i jak to naprawić

Published: at 13:37

Ikony SVG w WordPress - dlaczego inline to antywzorzec i jak to naprawić

Spis treści

Rozwiń spis treści

Popularny wzorzec, który nie powinien być popularny

Przeglądam kod motywów WordPress i widzę to regularnie. Tablica PHP z ikonami social media, gdzie każda ikona to pełny kod SVG wklejony jako string.

$options = array(
    'facebook' => array(
        'key'  => 'facebook',
        'icon' => '<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 24 24"><path d="M12 2C6.477 2 2 6.477 2 12C2 16.991 5.657 21.128 10.438 21.879V14.89H7.898V12H10.438V9.797C10.438 7.291 11.93 5.907 14.215 5.907C15.309 5.907 16.453 6.102 16.453 6.102V8.562H15.193C13.95 8.562 13.563 9.333 13.563 10.124V12H16.336L15.893 14.89H13.563V21.879C18.343 21.129 22 16.99 22 12C22 6.477 17.523 2 12 2Z"/></svg>',
    ),
    'instagram' => array(
        'key'  => 'instagram',
        'icon' => '<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 24 24">...</svg>',
    ),
    // ... kolejne ikony
);

$output[] = '<a href="' . esc_url($url) . '">' . $settings['icon'] . '</a>';

Działa? Technicznie tak. Ale to architektura, która płaci podatek przy każdym page view.

Policz sobie koszty

Pojedyncza ikona SVG to zazwyczaj 500-2000 bajtów kodu. Typowy zestaw social media (Facebook, Instagram, LinkedIn, Twitter/X, YouTube) to 5 ikon.

Przy 1 KB średnio na ikonę masz 5 KB nadmiarowego HTML-a w każdej odpowiedzi serwera.

A teraz pomnóż to przez liczbę podstron, na których te ikony się pojawiają. Footer z ikonami na 50 podstronach? To 250 KB transferu, który mógłby nie istnieć.

Co tracisz:

ProblemKonsekwencja
Brak cache przeglądarkiSVG ładowane od nowa przy każdym page view
Większy HTMLWolniejszy parsing DOM
DuplikacjaTa sama ikona renderowana osobno na każdej podstronie
Czytelność koduPHP zaśmiecony wielolinijkowymi stringami SVG
Edycja ikonWymaga zmian w PHP zamiast podmianki pliku
Niespójność wizualnaRóżne wersje tej samej ikony w różnych miejscach

Problem z kodem generowanym przez LLM

Jest jeszcze jeden aspekt, który staje się coraz bardziej widoczny w erze AI-assisted development.

Prosisz Claude’a, GPT czy Copilota o komponent z ikonami social media. Dostajesz działający kod z inline SVG. Tydzień później prosisz o kolejny komponent z tymi samymi ikonami. Dostajesz inny wariant SVG.

Efekt? Rozjechana ikonografia.

LLM nie ma pamięci o tym, jakiego wariantu ikony Facebook użył w poprzednim prompcie. Każda generacja to potencjalnie:

Widziałem projekt, gdzie ta sama ikona LinkedIn występowała w trzech różnych wariantach na jednej stronie. Nie dlatego, że ktoś świadomie wybrał różne style - tylko dlatego, że każdy fragment kodu został wygenerowany osobno.

Rozwiązanie: Single Source of Truth

Gdy trzymasz ikony jako zewnętrzne pliki, masz jedno źródło prawdy. Niezależnie od tego, ile razy poprosisz LLM o komponent używający ikony Facebook - zawsze odwołuje się do tego samego pliku facebook.svg.

// LLM generuje tylko referencję, nie całą ikonę
'icon' => 'facebook.svg',

Zamiast:

// LLM generuje pełny SVG - za każdym razem potencjalnie inny
'icon' => '<svg xmlns="http://www.w3.org/2000/svg" width="28"...',

To nie jest edge case. To staje się domyślny scenariusz w projektach, gdzie duża część kodu powstaje z pomocą AI. Więcej o pracy z LLM i jak unikać takich pułapek znajdziesz w artykule Subiektywnie o vibe codingu.

Lepszy wzorzec - zewnętrzne pliki SVG

Architektura, która ma sens:

Struktura plików

assets/images/social/
├── facebook.svg
├── instagram.svg
├── linkedin.svg
├── twitter.svg
└── youtube.svg

Kod PHP

$icons_url = get_stylesheet_directory_uri() . '/assets/images/social/';

$options = array(
    'facebook' => array(
        'key'  => 'facebook',
        'icon' => 'facebook.svg',
    ),
    'instagram' => array(
        'key'  => 'instagram',
        'icon' => 'instagram.svg',
    ),
);

// Generowanie HTML
$icon_html = sprintf(
    '<img src="%s" alt="%s" width="28" height="28" loading="lazy" />',
    esc_url($icons_url . $settings['icon']),
    esc_attr($social)
);

$output[] = sprintf(
    '<a target="_blank" rel="noopener noreferrer" href="%s">%s</a>',
    esc_url($url),
    $icon_html
);

Co zyskujesz:

Kiedy inline SVG ma sens

Nie twierdzę, że inline SVG jest zawsze złe. Jest kilka scenariuszy, gdzie ma uzasadnienie:

1. Dynamiczna zmiana koloru przez CSS

.icon-link:hover svg path {
  fill: currentColor;
}

Jeśli potrzebujesz, żeby ikona dziedziczyła kolor z rodzica lub zmieniała się przy hover - musisz mieć SVG w DOM.

2. Animacje zależne od DOM

Animacje SMIL lub JavaScript manipulujące ścieżkami SVG wymagają dostępu do elementów wewnątrz SVG.

3. Ikona używana tylko raz

Jeśli ikona pojawia się na jednej podstronie i nigdzie indziej - overhead osobnego requestu HTTP może nie mieć sensu.

4. Critical path rendering

Ikona above the fold, która musi być widoczna natychmiast bez dodatkowego roundtripa do serwera.

Hybrydowe podejście - SVG sprite

Jeśli potrzebujesz dynamicznych kolorów, ale nie chcesz duplikować kodu, rozważ SVG sprite:

<!-- Jeden plik sprite.svg z definicjami -->
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
  <symbol id="icon-facebook" viewBox="0 0 24 24">
    <path d="M12 2C6.477 2 2 6.477..." />
  </symbol>
  <symbol id="icon-instagram" viewBox="0 0 24 24">
    <path d="..." />
  </symbol>
</svg>

<!-- Użycie -->
<svg width="28" height="28"><use href="#icon-facebook" /></svg>

Sprite definiujesz raz (np. w headerze), a potem odwołujesz się przez <use>. Zachowujesz kontrolę CSS nad fill, ale kod nie jest duplikowany.

Podsumowanie

AspektInline SVGZewnętrzne SVGSVG Sprite
Cache przeglądarkiBrakTakCzęściowo
Rozmiar HTMLDużyMinimalnyŚredni
Dynamiczny kolor CSSTakNieTak
Lazy loadingNieTakNie
Edycja ikonWymaga PHPPodmiana plikuWymaga sprite

Domyślnie trzymaj się zewnętrznych plików SVG. Sięgaj po inline tylko wtedy, gdy masz konkretny powód - dynamiczne kolory, animacje, critical rendering path.

Nie dlatego, że “tak jest wygodniej pisać kod”.

Pamiętaj też, że optymalizacja kodu to tylko część układanki. Jeśli Twój serwer zwraca TTFB na poziomie kilku sekund, żadna ilość mikro-optymalizacji tego nie naprawi. Więcej o tym piszę w artykule Dlaczego hosting powinien być krokiem numer jeden.


Jakie jest Twoje zdanie? Daj znać w komentarzach.

Mateusz Zadorożny
Mateusz Zadorożny

Od 2012 roku moja praca przeplata się z WordPressem. Od 2017 pracuję z WooCommerce, bardzo dużo czasu poświęcając na testowanie różnych konfiguracji i rozwiązań. Łączę development z digital marketingiem tak, aby w e-commerce osiągnąć maksymalną skuteczność.

O mnie →
Zmień ustawienia prywatności Built with Astro