Спрайты не нужны!


В последнее время стало модно заявлять что спрайты не нужны, ведь у нас есть SVG.

Я сам давно и преданно люблю векторную графику и необычайно рад, что теперь можно использовать её в полный рост (если вам не нужно поддерживать IE8). Однако запросы к гуглу вида «svg background image» не приводили ни к чему, что было бы интереснее заметки Криса Койера. Хотелось следующего:

  • Работать с векторными иконками
  • Иметь возможность гибко изменять внешний вид через CSS.
  • Минимум сетевых запросов

Сначала я пошёл неправильным путём, используя встраиваемый SVG, именованные ресурсы и управление через внешние CSS-стили. Однако всё это выглядело крайне коряво и имело неприятную проблему с display:none. Вот вам небольшой пример (попробуйте переключить видимость).

Поскольку собственные изыскания завели в тупик, я задал вопрос в твиттере и Александр Бойченко мне всё доступно объяснил. А теперь это ещё раз сделаю я.

Итак, у нас есть некоторый SVG-файл. Пусть это будет звёздочка, залитая градиентом:

enter image description here

Прогоним код изображения через svgo и получим такую строку:

<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20"><linearGradient id="a" 
    gradientUnits="userSpaceOnUse" x1="20.227" y1="9.736" x2=".253" y2="9.736" 
    gradientTransform="matrix(0 1 -1 0 19.699 -.227)"><stop offset="0" stop-color="#00B2BF"/>
    <stop offset="1" stop-color="#914393"/></linearGradient><polygon fill="url(#a)" 
    points="16.616,10.013 19.699,14.458 14.302,14.819 12.749,20 9.102,16.005 4.083,18.022 
    4.933,12.68 0.226,10.013 4.933,7.347 4.083,2.005 9.102,4.021 12.749,0.027 14.302,5.208 
    19.699,5.569"/></svg>

Теперь нужно заставить работать это изображение как фон. Путь первый, неправильный — сохранить файл как star.svg и сделать что-то подобное:

.star {
    display: block;
    height: 20px;
    width: 20px;
    background: url(star.svg);
}

Более правильный способ — использовать data-uri. При этом для SVG, в отличие от растровой графики, использовать base64 не нужно. Нужно только указать mime-тип и кодировку текста.

.star {
    display: block;
    height: 20px;
    width: 20px;
    background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg"...</svg>');
}

Однако IE9 и IE10 отказываются понимать такое. Но не отказываются понимать SVG в принципе. Им нужно только немного помочь и выполнить URL-кодирование строки согласно RFC 3986 (например, функцией rawurlencode() в php или urllib.quote() в питоне). Получим вот такой код, от которого вытекают глаза, но который работает во всех браузерах. Обратите внимание, кодировку указывать не нужно.

.star {
    display: block;
    height: 20px;
    width: 20px;
    background: url('data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2F
        svg%22%20width%3D%2220%22%20height%3D%2220%22%3E%3ClinearGradient%20id%3D%22a%22%20gradientUnits
        %3D%22userSpaceOnUse%22%20x1%3D%2220.227%22%20y1%3D%229.736%22%20x2%3D%22.253%22%20y2%3D%229.736
        %22%20gradientTransform%3D%22matrix%280%201%20-1%200%2019.699%20-.227%29%22%3E%3Cstop%20offset%3
        D%220%22%20stop-color%3D%22%2300B2BF%22%2F%3E%3Cstop%20offset%3D%221%22%20stop-color%3D%22%23914
        393%22%2F%3E%3C%2FlinearGradient%3E%3Cpolygon%20fill%3D%22url%28%23a%29%22%20
        points%3D%2216.616%2C10.013%2019.699%2C14.458%2014.302%2C14.819%2012.749%2C20%209.102%2C16.005%204.
        083%2C18.022%204.933%2C12.68%200.226%2C10.013%204.933%2C7.347%204.083%2C2.005%209.102%2C4.021%2012.
        749%2C0.027%2014.302%2C5.208%2019.699%2C5.569%22%2F%3E%3C%2Fsvg%3E');
}

Естественно, всё это нужно делать не руками, а автоматизировать через Grunt и ему подобные сборщики.

Убедиться, что весь этот код работает вы можете открыв пример в песочнице.

Итого, мы получили относительно простой способ внедрения векторной графики в CSS как фоновые изображения без единого лишнего запроса и готовы к ретинизации мира.