Пришло время переосмыслить используемый нами подход к подготовке наборов фавиконов для современных браузеров и остановить безумие генераторов фавиконов. В наши дни фронтенд-разработчикам приходится иметь дело с более чем 20 статическими PNG-файлами только для того чтобы вывести на вкладке браузера или на сенсорном экране миниатюрный логотип сайта. В этом материале раскрывается более разумный подход к работе с фавиконами, который направлен на подбор минимального количества файлов, использование которых способно решить большинство «фавиконных» задач, стоящих перед современным веб-разработчиков.
Известно, что создание фавиконов — это гораздо сложнее, чем многим хотелось бы. Поэтому я, чтобы не мучить тех, кто уже достаточно от всего этого настрадался, кто точно знает, что делать, собрал всю суть статьи в паре примеров кода. Но я, всё равно, советую читать этот материал целиком.
Очень короткая версия статьи
Вместо того чтобы готовить для сайта десятки фавиконов — достаточно будет создать пять иконок и один JSON-файл.
Вот HTML-код, который попадает в браузер:
<link rel="icon" href="/favicon.ico"><!-- 32×32 -->
<link rel="icon" href="/icon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/apple.png"><!-- 180×180 -->
<link rel="manifest" href="/manifest.webmanifest">
Вот код, который предназначен для манифеста веб-приложения:
// manifest.webmanifest
{
"icons": [
{ "src": "/192.png", "type": "image/png", "sizes": "192x192" },
{ "src": "/512.png", "type": "image/png", "sizes": "512x512" }
]
}
Вот и всё. А если вы хотите узнать о том, как я до всего этого дошёл, на какие компромиссы мне пришлось пойти, и о том, как самостоятельно, с нуля, создать подобный набор файлов — читайте дальше. Ниже я всё объясню и приведу пошаговые примеры.
Длинная версия статьи, в которой даны все необходимые пояснения
Совершенство достигнуто не тогда, когда нечего добавить, а когда нечего убрать.
Антуан де Сент-Экзюпери
Понятие «фавикон» (favicon, favorite icon, значок для избранного) существует с начала 2000-х годов. Все мы видели фавиконы в списках вкладок браузеров — маленькие симпатичные изображения, которые помогают различать открытые страницы. Пользователи ожидают наличия фавиконов у сайтов. Это — одна из тех мелочей, внимание к которым со стороны разработчика сайта заставляет воспринимать этот сайт как некий серьёзный проект.
Даже компания Apple, у которой всегда были претензии эстетического плана, направленные на иконки, созданные не в Купертино, и которая не уделяла особого внимания фавиконам в Safari, наконец сдалась. Теперь фавиконы правильно отображаются на всех устройствах от Apple.
Если у вас есть общедоступный веб-сайт — у него должен быть фавикон. К сожалению, то, что пользователи воспринимают в виде одной иконки, на самом деле представлено множеством изображений.
Часто тяжёлый труд по созданию графических файлов, необходимых для поддержки постоянно растущего списка экранов и устройств, перекладывают на генераторы фавиконов. Никто, пребывающий в здравом уме, не станет тратить многие часы на ручное создание этих изображений. Мы, в конце концов, занимаемся разработкой сайтов, смысл нашей жизни не в том, чтобы угождать производителям браузеров.
Набор фавиконов, созданный популярным онлайн-генератором
Я, как создатель NanoID и сторонник минималистичного опенсорса, обычно склонен смотреть в несколько ином направлении. Какой набор графических файлов позволяет наиболее эффективно обеспечить веб-сайт фавиконами? Какие форматы являются устаревшими? Иконки каких типов можно заменить на другие, пойдя на небольшие компромиссы?
Размышляя об этом, я решил создать минимальный набор фавиконов, который подойдёт для всех ситуаций и будет работать во всех браузерах. Его единственный недостаток заключается в том, что в некоторых особых случаях он, хотя окажется работоспособным, не позволит добиться на 100% идеального результата.
Универсальный набор фавиконов
Вместо того чтобы создавать множество изображений разных размеров, я решил положиться на формат SVG и на возможности браузеров по уменьшению масштабов картинок. Если вы беспокоитесь о производительности — сейчас я внесу ясность в этот вопрос:
- Браузеры загружают фавиконы в фоновом режиме. Поэтому загрузка достаточно большого изображения фавикона не повредит производительности сайта.
- Применение формата SVG позволяет экономно хранить изображения, не являющиеся растровыми. Так, в случае с большинством логотипов, их хранение в формате SVG даёт гораздо меньший размер файла, чем использование формата PNG.
- В этом минималистичном наборе фавиконов имеется всего три PNG-изображения. Для оптимизации их размеров можно использовать продвинутые инструменты. Это позволяет решить проблемы тех пользователей, у которых нет безлимитного интернет-подключения.
Сейчас я расскажу о минимальном наборе значков, к которому меня привели исследование вопроса подготовки ресурсов для фавиконов и практика. Этот набор ресурсов должен работать во всех популярных браузерах и на всех устройствах, включая старые и новые.
I. Файл favicon.ico для устаревших браузеров
ICO-файлы, на самом деле, имеют структуру директорий. В них могут быть упакованы графические файлы разных размеров. Я рекомендую остановиться на одном изображении размера 32x32 пикселя. Если же это изображение плохо масштабируется до размера 16x16 (например, оказывается размытым), то вам стоит попросить дизайнера создать его высококачественную уменьшенную версию.
Не стоит увлекаться экспериментами со структурой папки для статических ресурсов и со средствами для улучшения кеширования ресурсов сайта. Предположим, у нас имеется сайт https://example.com
. Его фавикон должен находиться по адресу https://example.com/favicon.ico
. Некоторые программы, вроде RSS-читалок, пытаясь загрузить фавикон, просто запрашивают с сервера файл /favicon.ico
и не утруждают себя поисками этого файла где-то ещё.
II. Одна SVG-иконка с поддержкой тёмной и светлой темы для современных браузеров
SVG — это векторный графический формат, описывающий не пиксели, а кривые. SVG-файлы, при хранении некоторых больших изображений, оказываются эффективнее растровых форматов. На момент написания этого текста 72% браузеров поддерживают SVG-иконки.
Для подключения к HTML-странице SVG-значка в её коде, в разделе <head>
, должен быть тег <link>
, в котором имеются атрибуты rel="icon", type="image/svg+xml"
и атрибут href
со ссылкой на SVG-файл.
SVG-файлы содержат XML-данные, в состав которых может входить тег <style>
, содержащий CSS-код. Тут, как и в любом CSS-коде, могут использоваться медиазапросы, наподобие @media (prefers-color-scheme: dark)
. Это позволяет организовать подстройку внешнего вида значка под системную тему — тёмную или светлую.
III. PNG-файл размером 180x180 для устройств Apple
Если добавить веб-страницу на домашний экран iPhone или iPad — в качестве значка для её открытия будет использовано изображение, указанное в разделе страницы <head>
, в теге, который может выглядеть как <link rel="apple-touch-icon" href="icon.png">
.
Устройства iPad, начиная с iOS 8+, требуют использования изображений размером 180x180 пикселей. Другие устройства могут уменьшить изображение. Если подготовить исходное изображение достаточно высокого качества, то его уменьшение не повредит конечным пользователям (мы ещё об этом поговорим).
Хочу дать небольшой совет о подготовке значков, рассчитанных на устройства Apple. Значок будет выглядеть лучше в том случае, если вокруг основного изображения будет поле размером в 20 пикселей, и если фон значка будет закрашен каким-то цветом. Изображение можно обработать подобным образом, воспользовавшись любым графическим редактором.
IV. Манифест веб-приложения с PNG-значками размерами 192x192 и 512x512, рассчитанными на Android-устройства
- Манифест веб-приложения — это JSON-файл, содержащий сведения, необходимые браузеру для установки приложения на устройство. Формат этого файла предложен Google в рамках технологии PWA.
- Манифест подключается к веб-странице посредством тега, который может выглядеть как
<link rel="manifest" href="path.webmanifest">
. - В манифесте должно присутствовать поле
icons
, в котором содержатся ссылки на две иконки. Одна из них, размерами 192x192 пикселя, используется для значка приложения на домашнем экране. Другая, размером 512x512, применяется в качестве экрана-заставки, показываемого при загрузке PWA.
{
"icons": [
{ "src": "/192.png", "type": "image/png", "sizes": "192x192" },
{ "src": "/512.png", "type": "image/png", "sizes": "512x512" }
]
}
Не забыли ли мы о чём-нибудь?
Мы поговорили лишь о нескольких форматах фавиконов, но, на самом деле, существует гораздо больше их разновидностей. Некоторые из них не отличаются широкой известностью. Поэтому поговорим о том, как те значки, которые мы описали выше, ведут себя в различных ситуациях. Забегая вперёд, скажу, что, возможно, пришло время попрощаться с некоторыми форматами фавиконов, не получившими широкого распространения.
Иконки для плиточного интерфейса Windows
Браузер Microsoft Edge поддерживал иконки особого формата, используемые при закреплении сайтов в стартовом меню. В современных версиях Windows это уже не нужно.
Иконки для закреплённых вкладок Safari
Браузер Safari выдвигал особые требования для иконок, которые предназначены для закреплённых вкладок. Но, с выхода Safari 12, на таких вкладках можно использовать обычные фавиконы. Даже на apple.com больше не используется mask-icon
.
Атрибут rel=«shortcut»
Во множестве руководств (теперь устаревших) предлагается включать favicon.ico
в HTML с помощью следующей конструкции:
<link rel="shortcut icon" href="/favicon.ico">
Обратите внимание на то, что ключевое слово shortcut
не является допустимым значением атрибута rel
и никогда таковым не являлось. Вот отличная статья десятилетней давности, в которой можно найти соответствующие пояснения и указание на то, что конструкция rel="icon"
— это всё, что нужно.
Табло браузера Яндекс
Браузер Яндекс основан на Chromium. Его разработкой занимается крупнейшая российская поисковая система, которой принадлежит 20% рынка поиска в России. У этого браузера есть удобная функция, которая позволяет сайтам выводить актуальные данные в виджетах, закреплённых на особой панели, называемой Табло. Для реализации этого функционала нужен особый JSON-файл манифеста, загружаемой по ссылке, значением атрибута rel
которой является yandex-tableau-widget
. Но оказалось, что эта возможность особой популярностью не пользуется. Компания Яндекс удалила со своего сайта соответствующую техническую документацию. В результате для нормальной работы с сайтами в браузере Яндекс достаточно обычного файла-манифеста.
Браузер Opera Coast
Opera Coast — это экспериментальный браузер для iOS, который требовал использования иконок особого размера — 228x228. В 2017 году браузер исчез из App Store. Я сомневаюсь, что он пережил множество обновлений iOS, которые были выпущены с тех пор.
Собственно говоря, теперь, когда мы попрощались технологиями, ушедшими в небытие, поговорим о том, как подготовить универсальный набор фавиконов, подходящих для актуальных браузеров и устройств.
Создание универсального набора фавиконов
Вот пошаговый план действий по подготовке универсального минималистичного набора фавиконов. Приступая к реализации этого плана достаточно обзавестись единственным SVG-файлом с изображением, которое должно выводиться на фавиконах.
Шаг 1. Подготовка SVG-файла
Проверьте, чтобы ваш исходный SVG-файл был бы квадратным. Откройте исходный файл в вашей системной программе просмотра графики и проверьте ширину и высоту изображения. Если файл нуждается в правке — сделать это можно в любом SVG-редакторе. Например, в Inkscape можно изменить размеры документа, перейдя по пули File > Document Properties
. Выровнять логотип по центру изображения можно, прибегнув к команде Object > Align and Distribute
.
Сохраните файл с именем icon.svg
. Теперь давайте поработаем с кодом SVG-файла, подготовим этот файл к работе с темами, поддерживаемыми современными системами. Уточните у дизайнера вопрос о том, как должны меняться цвета в варианте изображения, рассчитанном на тёмную тему (если речь идёт о чёрно-белом логотипе, то достаточно просто поменять чёрный цвет на белый, а белый — на чёрный).
Теперь откройте SVG-файл в текстовом редакторе. Найдите элемент <path>
, в котором значение fill
отсутствует или представлено тёмным цветом. Добавьте в код медиа-запрос CSS, который срабатывает при изменении темы, и соответствующим образом поменяйте цвета этого элемента:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500">
+ <style>
+ @media (prefers-color-scheme: dark) {
+ .a { fill: #f0f0f0 }
+ }
+ </style>
- <path fill="#0f0f0f" d="…" />
+ <path class="a" fill="#0f0f0f" d="…" />
</svg>
Шаг 2. Создание ICO-файл
Откройте файл icon.svg
в растровом графическом редакторе. Я рекомендую GIMP — бесплатный многоплатформенный редактор.
Согласитесь с растеризацией SVG-изображения. Установите ширину и высоту изображения в 32 пикселя. Экспортируйте изображение в файл favicon.ico
, используя настройки 2 bpp, 8-bit alpha, no palette
.
Уменьшите изображение до размеров 16x16 пикселей и проверьте его качество. Если оно окажется слишком сильно размытым — лучше будет попросить дизайнера сделать особую версию этого изображения, хорошо выглядящую в маленьком размере.
Для того чтобы включить в состав favicon.ico
отдельную версию значка размером 16x16 пикселей, выполните следующие действия:
- Откройте
favicon.ico
, содержащий изображение размером 32x32 пикселя. - Создайте новый слой размером 16x16.
- Поместите изображение значка размера 16x16 пикселей на этот слой.
- Экспортируйте файл. GIMP сохранит каждый вариант значка в виде отдельной версии.
Шаг 3. Создание PNG-изображения
Снова откройте исходный SVG-файл в растровом редакторе и создайте изображение размером 512x512 пикселей. Экспортируйте его в файл icon-512.png
. Уменьшите изображение до размером 192x192 пикселя и экспортируйте его в файл icon-192.png
. Далее, уменьшите само изображение до размеров 140x140 пикселей, а размеры холста установите в 180x180. Экспортируйте изображение в файл apple-touch-icon.png
.
Шаг 4. Оптимизация PNG- и SVG-файлов
Лучший инструмент для оптимизации SVG-файлов — это SVGO. Выполните следующую команду:
npx svgo --multipass icon.svg
Для оптимизации растровых изображений отлично подходит веб-приложение Squoosh.
- Откройте в Squoosh файл
icon-512.png
. - Измените значение параметра
Compress
наOxiPNG
. - Включите установку
Reduce palette
. - Установите количество цветов в 64.
- Пользуясь слайдером сравните то, как выглядело изображение до оптимизации, с тем, как оно выглядит после оптимизации. Если вы заметите различия — увеличьте количество цветов.
- Сохраните файл.
Повторите эти действия для файлов icon-192.png
и apple-touch-icon.png
.
Шаг 5. Подключение значков в HTML
Теперь нужно подключить favicon.ico
и apple-touch-icon.png
к веб-странице.
Вот как это выглядит в коде статической страницы:
<title>My website</title>
+ <link rel="icon" href="/favicon.ico">
+ <link rel="icon" href="/icon.svg" type="image/svg+xml">
+ <link rel="apple-touch-icon" href="/apple-touch-icon.png">
Но мы рекомендуем использовать продвинутые средства для работы с кешем (речь идёт о включение в имя файла его хеша). Например, если вы пользуетесь Webpack с плагином html-webpack-plugin
, выполните следующие действия:
- Создайте шаблон
index.html
. - Добавьте этот шаблон в параметры плагина:
new HtmlWebpackPlugin({ template: "./view/index.html" });
- Опишите HTML-шаблон с включёнными в него ссылками (здесь для включения в шаблон ссылок на файлы используется ERB, но вы можете пользоваться и другим языком описания шаблонов):
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>My website</title> <meta name="viewport" content="width=device-width,initial-scale=1"> <link rel="icon" href="/favicon.ico"> <link rel="icon" type="image/svg+xml" href="<%= require('./icon.svg').default %>"> <link rel="apple-touch-icon" href="<%= require('./apple-touch-icon.png').default %>" > </head> <body></body> </html>
- Воспользуйтесь плагином copy-webpack-plugin для копирования
favicon.ico
без добавления к имени файла его хеша.
Совет: использование особого значка для окружения разработки
Разные фавиконы — это отличный механизм, позволяющий отличать продакшн-окружение от окружения для разработки ПО. Я полагаю, что использование альтернативного значка для окружения разработки крайне эффективно в деле предотвращения дорогостоящих ошибок.
Создадим файл favicon-dev.ico
, содержащий то же изображение, что и обычный фавикон, но изображение каким-то образом изменённое (это могут быть инвертированные цвета, или нечто подобное). Точно так же создадим и файл icon-dev.svg
.
Теперь настроим смену значков в HTML-шаблоне, проверяя условие process.env.NODE_ENV === 'production'
:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>My website</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
- <link rel="icon" href="/favicon.ico">
+ <link rel="icon" href="<%=
+ process.env.NODE_ENV === 'production'
+ ? '/favicon.ico'
+ : require('./favicon-dev.ico').default
+ %>">
<link rel="icon" type="image/svg+xml" href="<%=
- require('./icon.svg').default
+ process.env.NODE_ENV === 'production'
+ ? require('./icon.svg').default
+ : require('./icon-dev.svg').default
%>">
<link rel="apple-touch-icon" href="<%=
require('./apple-touch-icon.png').default
%>">
</head>
<body></body>
</html>
Шаг 6. Создание манифеста веб-приложения
При работе со статическим HTML-кодом нужно создать JSON-файл с именем manifest.webmanifest
:
{
"name": "My website",
"icons": [
{ "src": "/icon-192.png", "type": "image/png", "sizes": "192x192" },
{ "src": "/icon-512.png", "type": "image/png", "sizes": "512x512" }
]
}
Этот файл нужно подключить в HTML-коде:
<title>My website</title>
+ <link rel="manifest" href="/manifest.webmanifest">
<link rel="icon" href="/favicon.ico">
<link rel="icon" href="/icon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
При использовании Webpack можно воспользоваться плагином webpack-pwa-manifest:
plugins: [
…,
new WebpackPwaManifest({
name: 'My website',
icons: [
{ src: resolve('./icon-192.png'), sizes: '192x192' },
{ src: resolve('./icon512.png'), sizes: '512x512 }
]
})
]
Итоги
Как видите, благодаря существованию современных веб-стандартов создать универсальный набор фавиконов не так уж и сложно. Но, хотя ручное выполнение вышеописанных задач не должно отнять у вас слишком много времени, ещё лучше было бы, если бы их можно было автоматизировать. Если вы хотите создать средство для автоматизации подобных задач — пишите мне в Twitter. Я буду более чем счастлив вам помочь.
Как вы готовите фавиконы для своих веб-проектов?
Автор: ru_vds