Еще один способ использовать SVG в React. На этот раз удобный

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!

SVG-изображения можно вставлять непосредственно в html код, можно использовать символьные спрайты, теги <img>, <object> и даже <iframe>. Можно подключать SVG через data-url, css-backgrounds, css-filters и еще множеством способов. Но чтобы полноценно использовать всю суперсилу SVG, необходимо вставлять SVG-изображения непосредственно в html-разметку. Хотя на самом деле есть еще один способ. И он удобный.

Суперсила SVG

Одна из самых сильных сторон технологии SVG - возможность манипулировать стилями изображений через css. Это особенно важно для иконок, которые обязательно захочется подсветить на hover без использования дополнительных изображений.

Чтобы иметь возможность перекрашивать SVG через css, необходимо либо вставить SVG непосредственно в html, то есть «заинлайнить» их, либо использовать отдельный файл, символьный спрайт. Спрайт также должен быть вставлен в DOM. Ни одна другая техника не позволяет получить доступ к SVG из css. Рассмотрим эти техники подробнее.

Инлайнинг

Вставка SVG непосредственно в html это одновременно и самая простая и самая мощная с точки зрения кастомизации и манипуляции изображением техника.

<span>
  <svg viewBox="0 0 16 16" width="16" height="16">
    <!-- SVG -->
  </svg>
</span>

Такое изображение можно стилизовать через css, менять практически любое свойство и атрибут, даже анимировать его отдельные части. Но здесь есть ряд существенных ограничений:

  1. Если изображение большое, вся страница будет загружаться дольше

  2. Использование этой техники в js-фреймворках, даже с такими крайне мощными инструментами, как SVGR, сильно увеличивает размер js-бандла.

  3. Теряется контроль над загрузкой SVG, они перестают быть внешними изображениями. Вы не можете отдельно их хранить и кешировать, пренебречь их загрузкой на плохих соединениях и т.д.

Спрайт символов

Другой способ встраивания SVG, который позволяет стилизовать изображения через css, предполагает использование спрайта, состоящего из элементов <symbol>. Контент изображения хранится в отдельном скрытом файле и подключается в нужное место на странице через тег <use>.

<!-- Спрайт символов наверху страницы -->
<svg style="display:none">
  <symbol id="icon" viewBox="0 0 16 16" width="16" height="16">
    <!-- SVG -->
  </symbol>
</svg>

<!-- Использование -->
<span>
  <svg><use href="#icon" /></svg>
</span>

А если вы, как и Microsoft, не поддерживаете IE11, спрайт символов можно загружать по HTTP.

<svg>
  <use href="https://cdn.net/sprite.svg#example"/>
</svg>

К сожаление, использовать такой подход напрямую, то есть загрузить по HTTP содержимое отдельного SVG-изображения не получится, нужен именно спрайт. Вот так работать не будет:

<svg>
  <use href="https://cdn.net/icon.svg"/>
</svg>

К изображениям, подключенным через спрайт, можно получить доступ через css , правда, есть ограничения. Стилям не «пробиться» через shadow-boundary, границу, за которой начинается shadow-DOM и которая описывается тегом <use>.

Хорошие новости в том, что каскад продолжает работать, можно менять атрибуты fill и использовать currentColor в любом свойстве. Для большинства кейсов с иконками этого более чем достаточно:

<!-- Спрайт -->
<svg style="display:none">
  <symbol id="icon">
    <path fill="currentColor">
  </symbol>
</svg>

<!-- Добавляем иконке css-класс -->
<span>
  <svg class="icon"><use href="#icon" /></svg>
</span>

<!-- Красим SVG через css -->
<style>
  .icon {
    color: rebeccapurple;
  }
</style>

Спрайты удобны, но у них немало своих проблем, главная из которых - они плохо расширяемы. В конечном итоге спрайты разрастаются до огромных размеров и целиком подключаются на страницы ради использования одной-двух иконок.

Компромисс

Здесь не обойтись без компромисса. Нужно решение, которое загрузит на страницу только необходимые SVG-изображения, не будет рендерить их через javascript и позволит стилизовать их через css.

Таким решением может быть браузерный fetch! Нам нужен инструмент, который

  1. Загрузит SVG-изображения в браузере через fetch и закеширует их

  2. Добавит их в символьный спрайт

  3. Предоставит API для использования загруженных изображений в произвольном участке страницы через тег <use>.

Первым о таком решении задумался Chris Coyier еще в 2015 году, но оно так и не было оформлено и ждало своего дня. Сегодня этот день настал.

Handy SVG

Реализация называется Handy SVG, исходники и документация доступны на github, пакет публикуется в npm. Вам достаточно установить его:

npm i handy-svg

И использовать в React:

import {HandySvg} from 'handy-svg';
import iconSrc from './icon.svg';

export const Icon = () => (
    <HandySvg
        src={iconSrc}
        className="icon"
        width="32"
        height="32"
    />
);

Или в любом другом проекте с ванильным javascript:

import {injector} from 'handy-svg/lib/injector';

const src = "https://cdn-server.net/icon.svg";

// Загружает изображения и добавляет их в спрайт
injector.load(src);

// Доступ к id изображения
const id = injector.getId(src);

// Использование
const svg = `<svg class="icon"><use href="#${id}" /></svg>`;

Никаких проблем со стилизацией не возникнет:

.icon {
  color: rebeccapurple;
}

На страницу будут загружаться только необходимые изображения, вы сможете их закешировать, а в SPA-приложениях запросы конечно же не будут отправляться дважды. Ваш спрайт не будет разрастаться и вы вообще не будете задумываться о его существовании.

Конечно это решение имеет ряд ограничений. Например, почти невозможно избавиться от FONI (Flash of No Icons), состояния загрузки, при котором на странице отсутствуют иконки. Тем не менее, из всех возможных способов работы с SVG-изображениями в вебе, этот представляется наиболее удобным.


Пул-реквесты приветствуются и я буду рад любому фидбеку.

Источник: https://habr.com/ru/post/672984/


Интересные статьи

Интересные статьи

Январь этого года был для меня не только чередой праздников, но и поводом отметить год, как мы полностью переехали на новый платежный шлюз. Для нас, как для сервиса подписки на духи, это одна из ключе...
В последнее время много статей о прокрастинации. Это означает, что людей постиг этот недуг, некоторые с ним справились и делятся опытом. А чуть больше полугода назад случился массовый...
Поговорим о том, как прекратить копипастить между проектами и вынести код в переиспользуемый подключаемый бандл Symfony 5. Серия статей, обобщающих мой опыт работы с бандлами, проведет на практик...
TL;DR 27-29 февраля мы проводим Слёрм Аджайл. Как мы любим, в нем будет 20% теории и 80% практики (тренинга). Слёрм Аджайл ведут эксперт-консультант Марина Алекс и практик аджайла, директор по ...
Дисклеймер Уважаемый читатель! Если вы не имеете понятия, что такое React и Redux, читать дальше не имеет смысла, дальше технический бред. Я серьезно, понимание к чему эта записка, требует работ...