Тёмная и светлая темы для SVG

Использование CSS функции light-dark() для реализации светлого и тёмного режима для SVG иконок,включая SVG, используемые с HTML элементом img или в качестве CSS свойства background-image.

Базовый подход

У SVG есть уникальное преимущество перед другими форматами изображений: CSS можно включить в разметку самого изображения. Для инлайн SVG иконок currentcolor и CSS переменные — простые способы реализации тёмного режима. Когда SVG используется как обычный формат изображения, ни один из этих подходов не работает. Решением этой проблемы является CSS функция light-dark(). Функция light-dark() для не инлайн SVG иконок работает в Firefox, Chrome и Edge. В Safari обнаружен баг, и, похоже, вскоре его исправят.

Ниже представлены два SVG круга. Один — <div>, использующий CSS свойство background-image. Второй — HTML элемент <img>. Их цвет fill зависит от системных предпочтений пользователя:

<div style="background-image: url('images/circle.svg'); width: 40px; height: 40px;"></div>
<img width="40" src="images/circle.svg" alt="">

Содержимое файла circle.svg:

<svg style="color-scheme: light dark;" fill="light-dark(black, white)" viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg"><circle cx="5" cy="5" r="5"/></svg>

Свойство color-scheme внутри SVG фактически говорит: Вот цветовые схемы, которые я могу поддерживать, но фактически схема, используемая SVG, может управляться извне, либо CSS свойством color-scheme, либо мета-тегом color-scheme в <head> HTML-документа. Код внутри SVG файла определяет, какие цветовые темы может использовать SVG, а код в HTML документе указывает, какую тему он хочет использовать.

<img width="40" src="images/circle.svg" alt="">
<img style="color-scheme: light;" width="40px" src="images/circle.svg" alt="">
<img style="color-scheme: dark;" width="40px" src="images/circle.svg" alt="">
Зависит от системных предпочтений
Используется светлая цветовая схема, независимо от системных предпочтений
Используется тёмная цветовая схема, независимо от системных предпочтений

Следующий код в <head> HTML документа указывает, что документ использует только тёмный режим, поэтому значение dark, указанное в light-dark(), будет использоваться любым SVG изображением, указавшим, что оно может поддерживать тёмный режим через color-scheme:

<meta name="color-scheme" content="dark" />

Другие подходы

Медиа-запрос prefers-color-scheme

Медиа-запрос prefers-color-scheme работает для SVG, не являющихся инлайн, в Chrome/Edge и Firefox, но не в Safari.

Медиа-запрос prefers-color-scheme можно использовать внутри блока <style> в SVG:

<svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
<style>
rect { fill: black; }
@media (prefers-color-scheme: dark) {
rect { fill: white; }
}
</style>
<rect width="32" height="32"/>
</svg>

На результаты запроса влияют как CSS свойство color-scheme, так и HTML метатег color-scheme.

<div style="color-scheme: light">
<img src="images/square.svg">
</div>
<div style="color-scheme: dark">
<img src="images/square.svg">
</div>

Элемент <picture>

Элемент <picture> может отображать одно изображение для тёмного режима и другое — для светлого. Для этого необходимо экспортировать одно и то же SVG-изображение в два разных файла. Разметка <picture> содержит больше кода, чем простой тег <img>, и должна повторяться каждый раз, когда используется иконка. В отличие от элемента <picture>, использование функции light-dark() в разметке SVG также работает для фоновых CSS изображений.

Комментарии


Дополнительные материалы

Предыдущая Статья

Возможности middleware в Laravel

Следующая Статья

Уменьшение сложности CSS с псевдоклассом :is()