Картинка в Base64 для CSS
Что на самом деле решает встраивание
Задача почти всегда формулируется одинаково: «есть маленькая иконка, не хочу тащить ради неё отдельный файл». Строка Base64 внутри background-image действительно убирает один HTTP-запрос — браузер получает пиксели вместе с таблицей стилей и рисует их, не открывая новое соединение.
Цена известна заранее и не зависит от картинки. Кодировка укладывает каждые три байта в четыре печатных символа, то есть текст на треть длиннее исходника, плюс приставка вида data:image/png;base64,. Иконка на 214 байт станет строкой примерно в 290 символов — терпимо. Фотография на 3 МБ станет текстом на 4 МБ, и её уже некуда девать.
Второй расход менее очевиден и обычно дороже первого: встроенная картинка перестаёт кешироваться отдельно. Отдельный sprite.png браузер скачает один раз и будет отдавать из кеша хоть год. Тот же спрайт внутри styles.css живёт ровно столько, сколько живёт версия стилей: поменяли один отступ в CSS — пользователь снова качает все встроенные картинки. На проекте, где стили правят каждую неделю, это прямой убыток.
Третий момент — CSS блокирует отрисовку. Пока файл стилей не скачан и не разобран целиком, браузер не покажет ничего. Раздув styles.css на 300 КБ инлайновой графики, вы отодвигаете первый кадр для всех страниц сайта, включая те, где этих иконок нет.
Отсюда рабочее правило: встраивать имеет смысл единицы килобайт — галочки, стрелки, точечные подложки, состояния чекбокса, маленький логотип в шаблоне письма. Всё, что больше 5–10 КБ, почти всегда выгоднее оставить обычным файлом.
Когда обмен точно выгоден
Есть три ситуации, где инлайн выигрывает почти без оговорок. Первая — письма. Почтовые клиенты режут внешние картинки до того, как получатель нажмёт «показать изображения», а data: в теле письма отображается сразу; правда, Gmail и Outlook встроенные картинки тоже фильтруют, поэтому проверять надо на реальных адресах, а не в превью редактора. Вторая — однофайловые сборки: страница-отчёт, которую пересылают архивом, или HTML-виджет, вставляемый в чужую CMS без доступа к статике. Тут внешних ссылок просто нет. Третья — критический CSS в <head>: логотип и иконка загрузки, которые обязаны появиться в первом кадре, до того как придёт основная таблица стилей.
И зеркальный список: не встраивайте фотографии, картинки, которые повторяются на многих страницах, и всё, что вы планируете отдавать через CDN с длинным кешем.
Как получить строку
Кодировщик изображение в Base64 работает целиком в браузере: файл читается через FileReader, содержимое никуда не отправляется. Порядок такой.
- Нажмите на карточку Inject Image — по клику откроется системный выбор файла. Поле принимает маску
image/*, то есть любой растр: PNG, JPEG, WebP, GIF. Перетаскивание в эту зону не обрабатывается, только клик. - Посмотрите на карточку System Status. До загрузки там
READY FOR TRANSMISSION, во время чтенияPROCESSING SIGNAL..., послеTRANSMISSION SUCCESSFUL. Это единственный индикатор готовности — прогресса в процентах нет. - Проверьте превью: выбранная картинка появляется в соседней карточке вместо надписи
No data input. Если превью пустое, файл не растр либо повреждён. - Заберите результат из поля Base64 Output с подсказкой
Output stream.... Строка приходит целиком, уже с приставкой и MIME-типом — дописыватьdata:image/png;base64,руками не надо. - Нажмите Copy Signal. Кнопка выделяет содержимое поля и копирует его; на две секунды подпись меняется на
SIGNAL COPIED, потом возвращается. - Перед следующим файлом нажмите Clear. Кнопка перезагружает страницу — это гарантированная очистка, но и превью, и строка исчезнут без предупреждения.
Строку остаётся вставить в стили:
.ok::before {
content: "";
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQ...);
}
Кавычки внутри url() не обязательны, но с ними безопаснее: некоторые сборщики иначе спотыкаются о символы + и / в теле кодировки.
Ошибки, на которые уходит вечер
Кодируют то, что надо было сначала сжать. Самая частая. Снимок с телефона весит 3–4 МБ, после кодирования это 4–5 МБ текста, редактор начинает подтормаживать на файле стилей. Уменьшите картинку по пикселям и пережмите её сжатием изображений до кодирования — вес строки падает пропорционально весу файла.
Ждут, что инструмент отдаст оптимизированный формат. Он не конвертирует. Что подали на вход, то и окажется внутри строки: PNG останется PNG, JPEG — JPEG. Хотите WebP внутри data: — сначала получите файл .webp, потом кодируйте.
Копируют строку мышью и теряют хвост. В поле вывода лежат десятки тысяч символов, и выделение перетаскиванием почти всегда обрывается. Обрезанная строка даёт битую картинку без ошибки в консоли — просто пустой блок. Пользуйтесь Copy Signal, а результат при сомнении прогоняйте через декодер Base64 в изображение: если превью показывает вашу картинку, строка целая.
Забывают нажать Clear. Поле не очищается само при выборе нового файла до момента, пока чтение не завершилось, и легко скопировать строку от предыдущей картинки — визуально они неотличимы.
Встраивают SVG через Base64. Технически можно: файл читается как любой другой. Но векторную разметку в CSS вставляют в исходном виде через url("data:image/svg+xml,...") с процентным экранированием — запись короче, читается глазами и правится без перекодирования. Base64 для SVG оправдан там, где среда не переносит угловые скобки и кавычки в значении.
Кладут base64 в тег <img src> на каждой карточке списка. Двадцать товаров — двадцать копий строки в HTML, который не кешируется вовсе. Здесь инлайн проигрывает обычным ссылкам с большим отрывом.
Пересчитывают вес на глаз. Прикинуть длину строки можно арифметикой: размер файла в байтах делите на 3, умножаете на 4 и округляете вверх, плюс около 20 символов приставки. Файл на 4096 байт даёт 5464 символа тела. Если считать лень, вставьте строку в любой редактор и посмотрите счётчик символов — он и будет весом в байтах, потому что все символы Base64 однобайтовые в UTF-8.
Думают, что инлайн ускорит сайт сам по себе. На HTTP/2 и HTTP/3 стоимость лишнего запроса к тому же домену невелика: соединение уже установлено, заголовки сжаты. Выигрыш от встраивания одной иконки измеряется единицами миллисекунд, а проигрыш на кеше — сотнями килобайт повторной загрузки. Инлайн стоит применять точечно, а не как политику.
Если кодировать надо не картинку, а шрифт, PDF или произвольный файл, для этого есть отдельный кодировщик файла в Base64. Остальные инструменты набора собраны в разделе Base64.
Насколько строка тяжелее исходного файла?
Примерно на 33 процента плюс короткая приставка с MIME-типом. Это свойство самой кодировки: три байта данных превращаются в четыре печатных символа. Файл на 1 КБ даёт около 1,37 КБ текста. Обратите внимание, что gzip и brotli на сервере ужимают Base64 хуже, чем исходный бинарник, — сжатые форматы вроде PNG и JPEG внутри строки повторно почти не жмутся.
Какой максимальный размер файла принимает кодировщик?
Жёсткого лимита в коде страницы нет — ограничивает память вкладки и терпение редактора, в который вы вставите результат. Практическая граница другая: строку длиннее нескольких сотен килобайт больно держать в репозитории и в диффах. Если получилось много, это сигнал, что картинку не стоило встраивать.
Уходит ли моя картинка на сервер?
Нет. Файл открывается браузерным `FileReader` прямо с диска, страница переводит байты в текст на месте и сетевых запросов с содержимым не делает. Поэтому через кодировщик можно пропускать внутренние макеты и скриншоты рабочих систем.
Почему Copy Signal ничего не скопировал?
Кнопка копирует через выделение содержимого поля, и это иногда блокируется расширениями браузера или политикой корпоративного профиля. Запасной путь: кликните в поле `Output stream...`, нажмите Ctrl+A, затем Ctrl+C — результат тот же.
Можно ли закодировать несколько картинок сразу?
Нет, пакетного режима на странице нет: один файл за проход, а кнопка **Clear** перезагружает страницу перед следующим. Для набора из десятка иконок разумнее собрать SVG-спрайт или подключить их обычными файлами — это и быстрее в работе, и лучше для кеша.