От автора: Возможно, что вы уже слышали про схему data: URI. Это действительно замечательный способ встраивания какого-нибудь ресурса, для загрузки которого обычно потребовался бы отдельный HTTP запрос. Формат записи, использующийся в схеме data: URI, может варьироваться. Обычно вы просто указываете, к какому типу относится встраиваемый ресурс (например, image/png), точка с запятой, а затем сами данные файла.
Например:
1 |
<img src='data: ... '> |
или:
1 2 3 |
.bg { background: url('data: ... '); } |
Для растровых изображений, таких как PNG, данные самого изображения должны быть представлены в кодировке base64. Я не супер-эксперт в данной теме, но если я правильно понял, кодировка base64 является безопасной для использования в документах типа HTML или CSS, потому что в ней используются только 64 символа, являющиеся безопасными для использования в подобного рода документах.
Слева вы видите исходные данные изображения в формате PNG, содержащие символы, которые потенциально могут нанести вред целостности HTML документа. А справа – те же самые данные, закодированные с помощью base64 и представленные в виде безопасных символов.
Пожалуй, лучше будет прочитать ответ Дэйва Маркла (Dave Markle) на сайте Stack Overflow:
Вы никогда не можете быть уверенными, что некоторые протоколы не будут интерпретировать ваши бинарные данные, как управляющие символы (например, модем), или ваши бинарные данные не могут быть испорчены в результате того, что основной протокол воспринял их, как специальную последовательность символов (например, то как FTP трактует конец строки).
Поэтому, чтобы избежать возможных проблем, разработчики кодируют бинарные данные в символы. Base64 – как раз один из таких способов кодирования.
Base64 выглядит, как бессвязный набор символов, и относительно веба такой набор обычно ассоциируется с процессом сжатия. Но он не является сжатием. На самом деле он даже немного больше исходных данных, потому что, цитируя Джона Скита (Jon Skeet) в том же обсуждении на сайте Stack Overflow:
Происходит преобразование 3 байтов данных в 4 символа, плюс может происходить добавление пробелов/других символов в конце.
Я не уверен, как на этом сказывается сжатие gzip. Но мне хочется рассмотреть здесь, что происходит с SVG. Вы можете применять data: URI для SVG:
1 |
<img src='data:image/svg+xml; ... '> |
1 2 3 |
.bg { background: url('data:image/svg+xml; ... '); } |
В случае с SVG вы не обязаны преобразовывать данные с помощью base64. И опять же, не являясь экспертом в данной теме, думаю, что в синтаксисе SVG просто отсутствуют какие-либо «вредные» символы. Это как XML и HTML, поэтому SVG безопасно использовать в HTML. Вы можете оставить кодировку UTF-8 и вставить синтаксис svg прямо в код! Вот так:
1 |
<img src='data:image/svg+xml;utf8,<svg ... > ... </svg>'> |
1 2 3 |
.bg { background: url('data:image/svg+xml;utf8,<svg ...> ... </svg>'); } |
И поскольку мы можем так делать, и мы знаем, что base64 часто увеличивает размер данных, может быть, тогда оставить так, как есть? Да. А в качестве бонуса можно упомянуть, что чистый синтаксис svg лучше сжимается с помощью gzip, потому что он более повторяющийся, чем base64. Предположим, что вам нужны два варианта одной иконки (красный и желтый). Вы можете повторно использовать тот же SVG синтаксис, просто изменив цвет заливки. Для Gzip это будет сущий пустяк. Спасибо Тоду Паркеру (Todd Parker) за этот совет. И, кстати, такой подход используется в Grunticon, который вставляет SVG в кодировке UTF-8 с помощью data: URI в CSS код.
Тест
Чтобы протестировать этот подход, я скачал три SVG иконки с сайта IcoMoon.
Иконка cog.svg — 1,026 байтов
Иконка play.svg — 399 байтов
Иконка replay.svg — 495 байтов
Я оптимизировал их с помощь инструмента SVGO, чтобы подготовить их для вставки с помощью data: URI (пробелы были удалены, хотя я думаю, что это необязательно).
Иконка cog.svg — 685 байтов
Икока play.svg — 118 байтов
Иконка replay.svg — 212 байтов
Затем я преобразовал их с помощью конвертера base64.
Иконка cog.svg — 916 байтов — 133% от исходного размера
Иконка play.svg — 160 байтов — 136% от исходного размера
Иконка replay.svg — 283 байтов — 134% от исходного размера
По-моему, логично, не так ли? Если на каждые 3 байта приходится 4 символа, это дает нам 133%, с различным варьированием дополнительных пробелов/других символов для достижения нужного размера.
Может быть, это выглядит супер-очевидным. Но в любом случае мне хочется сказать, что если вы будете использовать data: URI для вставки SVG, у вас нет причин использовать для этого кодирование в base64.
Спасибо Мэтту Флэшену (Matt Flaschen) за его письмо, отправленное мне несколько месяцев назад. Именно оно помогло мне разобраться в данной теме.
Автор: Chris Coyier
Источник: //css-tricks.com/
Редакция: Команда webformyself.
Комментарии (2)