Systém SVG ikon s Gulpem

Michael Zrychlení webu, JavaScript, CSS, HTML

Alternativou k použití font ikon pro web jsou SVG sprity. Jak ušetřit čas a námahu při jejich tvorbě, si ukážeme v tomto článku.

Gulp a SVG ikony

Pokud používáte, nebo chcete při vývoji webu použít ikony, je dobré si kolem nich vytvořit nějaký systém. Populární je použití font ikon, což jsou znakové sady, které mají místo znaků ikony. V markupu jsou pak použity přidáním specifické třídy na <i> nebo <span> elementy. Font ikony mají u starších prohlížečů (čti IE 8 a starší, Safari 5, Android 2.3) lepší podporu, než inline SVG. Ale my se budeme zabývat právě SVG. Následující postup předpokládá základní znalost SVG a práce s Gulpem.

SVG sprity

SVG zdroj lze jednodušše vložit do markupu. To ale není při množství ikon zrovna systematické. Proto si vytvoříme něco jako SVG spritesheet, kdy se každá ikona obalí <symbol> tagem a vloží do jediného SVG dokumentu. 

<!-- Spritesheet soubor ikony.svg -->
<svg xmlns="http://www.w3.org/2000/svg">

    <symbol id="ikonka-1" viewBox="0 0 100 100">
        <!-- Cesty, tvary apod. --> 
    </symbol>

    <symbol id="ikonka-2" viewBox="0 10 120 60.5">
        <!-- Cesty, tvary, apod. -->
    </symbol>

</svg>

Každý <symbol> by měl mít unikátní ID. Díky značce <use> pak lze napříč dokumentem duplikovat jednotlivé symboly (ikony) přes atribut href, odkazující na dané ID symbolu (starší specifikace pro odkazy uvádějí atribut xlink:href). Způsob zobrazování ikon je tedy jiný, než u klasických spritů.

<!-- Vložení SVG ikonky ze spritesheetu -->
<svg class="icon"><use href="ikony.svg#ikonka-1"></svg>

Značka <use>

Více k <use> si můžete přečíst zde. Výhodou tohoto přístupu je především čistší zápis a fakt, že s SVG je pak možné stylovat CSSkem a manipulovat Javascriptem, téměř jako by bylo vloženo inline. Bohužel pouze „téměř“, protože takto vložené SVG je omezené hranicí skrytého DOMu (více ve článku výše). Taky šetříme uživatelům data, protože se ikony stáhnou jen jednou. To samozřejmě také šetří požadavky na server a pomáhá rychlosti načítání, ikdyž s rozšiřujícím se HTTP/2 už to nemusí být nutně pravda.

Nevýhodou linkování SVG tímto způsobem je pak to, že v IE nelze odkazovat na konkrétní soubor spritesheetu, viz příklad výše. Vyřešit se to dá buď pomocí polyfillu SVG for Everybody, nebo prostým vložením spritesheetu do stránky.

<!-- Pro IE je třeba polyfill nebo vložit sprity inline -->
<body>

    <div style="display: none;">
        <?php include_once("ikony.svg"); ?>
    </div>

    <!-- Po vložení spritů pak stačí odkazovat přes ID -->
    <svg class="icon"><use href="#ikonka-1"></svg>

<!-- ... -->

Gulp + svgstore

Pokud nechcete sprity vytvářet ručně, můžete použít nástroje jako iconizr a IcoMoon, nebo celou tvorbu automatizovat pomocí Gulpu a svgstore. Vytvoříme úlohu v Gulpu, která poskládá spritesheet obsahující všechny SVG ikony z určitého adresáře. Každá ikona bude mít ID atribut podle názvu souboru.

const gulp = require('gulp')
const svgstore = require('gulp-svgstore')

// Cesty k ikonkám a adresáři pro výstup
const path = {
  icons: 'adresar/ikonek/**/*.svg',
  images: 'adresar/obrazku'
}

// Build spritesheetu z ikonek v adresáři
gulp.task('svg-spritesheet', () => {
  return gulp
    .src(path.icons)
    .pipe(svgstore({ inlineSvg: true }))
    .pipe(gulp.dest(path.images))
})

Parametr "inlineSvg" pro svgstore je důležitý pokud vkládáte spritesheet inline, např. kvůli podpoře IE. Vynechá totiž z výstupu <?xml ?> značku a DOCTYPE deklaraci. Pokud v <use> značce odkazujete přímo na konkrétní soubor, tak můžete parametr vynechat.

Minifikace a další ošetření

SVG často obsahují z komentáře a další balast z editoru, který na webu nepotřebujeme. A když už je v úloze zpracováváme, není špatný nápad je rovnou i ošetřit. Kromě toho by bylo dobré rovnou provést i minifikaci. Kvůli pozdějšímu stylování ikon lze také odstranit inline styly a fill atributy. A pro lepší přehlednost můžeme ID ikon přidat prefix. To provedeme pomocí balíčků svgmin, rename a cheerio.

// ...
const svgmin = require('gulp-svgmin')
const rename = require('gulp-rename')
const cheerio = require('cheerio')

// ...

gulp.task('svg-spritesheet', () => { 
  return gulp
    .src(path.icons)
    .pipe(svgmin()) // Minifikace
    .pipe(cheerio(
      run: function ($) {
        $('[fill]').removeAttr('fill') // Odstraní fill atributy
        $('style').remove() // Odstraní style tagy
      },
      parserOptions: { xmlMode: true }
    ))
    .pipe(rename({ prefix: 'icon-' })) // Přidá prefix před ID ikon
    .pipe(svgstore({ inlineSvg: true }))  
    .pipe(gulp.dest(path.images)) 
})

A jakým způsobem pracujete s ikonami vy? Používáte SVG sprity, ale skládáte je jinak? Dejte vědět nám i ostatním v komentářích

Přidat komentář

Právě odpovídáte na existující komentář. Zrušit

Komentáře

Novinky z blogu

Zachycení událostí CSS animací v Javascriptu

CSS animace dokázaly na mnoha místech nahradit Javascript, který byl dříve jedinou schůdnou možností. Nejen pro svou jednoduchost jsou stále populárnější. Jenže co, když chci...

Další články