В этой статье мы увидим, как сделать не просто кнопки, а кнопки-иконки, доступные для людей с ограниченными возможностями, с помощью SVG и CSS, не перегружая HTML-код встроенным кодом <svg>
, но при этом используя возможность делать разные настройки.
Сначала давайте определим, чего мы хотим достичь при выводе нашего элемента-кнопки с иконкой:
- Интерактивности;
- Управления с клавиатуры;
- Доступности;
- Настраиваемости
… и мы достигнем всего этого с помощью только HTML и CSS! Ведь это же волшебство (It’s magic, isn’t it)?
Для примера будем делать кнопку для загрузки файлов.
Разметка примера с учетом доступности для людей с ограниченными возможностями
Нам понадобится только элемент <button>
, в который для решения проблем с доступностью можно добавить атрибут aria-label="Download File"
:
1 | <button aria-label="Download File"></button> |
Если вы не хотите использовать пустой элемент, то можете использовать для решения проблемы с доступностью элемент с классом .sr-only
, чтобы спрятать поясняющий текст от основных пользователей. Такой класс можно описать самостоятельно или использовать из какого-либо css-фреймворка.
1 2 3 | <button> <span class="sr-only">Download File</span>; </button> |
Вы можете использовать атрибут aria-label
для добавления значка к кнопке или скрытому элементу, читаемому только вспомогательными технологиями, - здесь выбор за вами. Используя элемент кнопки <button>
, мы уже решили первые три пункта нашего контрольного списка, поскольку он интерактивен, доступен с клавиатуры и доступен по умолчанию. Не требуется атрибут tabindex
или код JavaScript, чтобы сделать этот элемент доступным с клавиатуры.
Настраиваем под себя
Итак, как мы можем изменить цвета, размеры, добавить градиенты, используя одно изображение SVG из нашего CSS? Ответ заключается в использование очень широко поддерживаемых свойств mask-*
!
Единственное ограничение - значок источника должен быть черным на прозрачном или белом фоне. Это потому, что свойство маски использует чистый черный цвет для отображения видимой части фона, а белый или прозрачный цвет используется для затемнения фонового слоя.
Давайте начнем добавлять базовый стиль к нашей кнопке, чтобы настроить позиционирование и блочную модель:
1 2 3 4 5 6 7 8 9 10 11 | .IconButton { width: 56px; height: 56px; appearance: none; border-radius: 50%; border: 0; background-color: #000; cursor: pointer; padding: 0; position: relative; } |
Теперь мы собираемся использовать псевдоэлемент ::before
для добавления иконки. Псевдоэлемент с абсолютным позиционированием полезен для математического центрирования иконки, но в то же время он позволяет нам оптически центрировать иконку, когда нам это нужно. Стили:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | .IconButton::before { /* Код, связанный с позиционированием */ content: ""; display: block; /* width и height должны быть всегда равными */ width: 50%; height: 50%; background: #fff; pointer-events: none; /* это позволяет сделать при необходимости оптическое центрирование */ position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); } |
Теперь мы можем добавить наш волшебный код с масками. Прежде всего, нам нужна иконка, причем в формате SVG, поскольку мы хотим, чтобы она масштабировалась без потери качества. Мы будем использовать эту иконку в своем примере.
Используя свойства группы mask-
, мы можем установить нашу иконку, как маску элемента, так же, как мы это делаем с такими инструментами дизайна, как Sketch, Figma и другими. Давайте добавим эти свойства:
1 2 3 4 5 6 7 8 9 | .IconButton::before { /* Весь предыдущий код... */ /* Код для маски */ mask-image: url("https://cdn.glitch.com/a10b6199-a788-4cef-8bd8-21f95dbcba93%2Fdownload-cloud.svg?v=1571346192759"); mask-position: center; mask-repeat: no-repeat; mask-size: contain; } |
Как видите, здесь мы определили четыре вещи:
- Свойство url маски: наша черная svg-иконка;
- Позиция маски: установить всегда по центру;
- Повторение маски: мы отключили эффект плитки (повторяемости).
- Размер маски: мы устанавливаем его так, чтобы он содержался в доступном пространстве, поэтому значок всегда будет полностью видимым.
Вы могли заметить, что эти свойства аналогичны (и действуют), как свойства группы background. Основное отличие заключается в том, что изображение используется в качестве маски и делает наш элемент «прозрачным» там, где изображение является черным, а белая (или прозрачная) часть изображения используется для скрытия того, что находится на фоне. Наш значок здесь белый, потому что мы установили background: #fff;
на псевдоэлементе, а svg-иконка заполнена черным цветом #000
.
Поддержка браузерами свойств вида mask-
Свойства для формирования маски хорошо поддерживаются всеми современными браузерами:
Исключение составляют все версии IE, Opera Mini и US Browser для Android, а также некоторые другие браузеры, мало используемые в массе своей.
Если по какой-то странной причине вам необходимо поддерживать устаревшие браузеры, которые не поддерживают эти свойства, вы можете постепенно улучшать код, чтобы обеспечить минимальное взаимодействие с пользовательским интерфейсом.
Имейте в виду, что когда мы говорим о "минимальном взаимодействии пользовательского интерфейса", мы имеем в виду, что какие-то элементы могут выглядеть иначе, но работают они именно так, как ожидалось, не нарушая взаимодействия с пользователем. Это не означает "добавить тонну кода для старых браузеров, чтобы воспроизвести внешний вид элемента", потому что этот код будет загружен даже современными браузерами, замедляя отрисовку страницы, но никогда не будет использоваться.
Первый результат применения SVG-маски
Теперь мы должны увидеть что-то вроде этого:
Таким образом, вы можете изменить фон, добавить градиенты и сделать значки затухающими, залив их градиентом от черного до прозрачного цвета.
Внутри mask-image
вы также можете использовать значок из файла SVG-спрайта!
1 | mask-image: url("path/to/sprite.svg#my-icon-id"); |
Довольно круто и масштабируемо!
Давайте посмотрим на пример использования разных значков и изменения фона для псевдоэлемента ::before
:
Первая кнопка использует полностью черную иконку svg, вторая добавляет линейный градиент к псевдоэлементу ::before
, а третья использует иконку, заполненную градиентом от черного к прозрачному цвету. При создании css-кода вы можете даже анимировать все, что захотите. Также вы можете комбинировать пользовательские (кастомные) свойства, или css-переменные, чтобы передать путь иконки из html и легко обрабатывать их с помощью JavaScript, используя метод setProperty()
, например, так:
1 | myelement.style.setProperty ("- icon", "images/icons/like.svg"); |
В примере вместо JavaScript использовано стилевое свойство style="--icon: url(https://cdn.glitch.com/...)"
, указывающее путь к svg-иконке. Вы можете заменить его любым другим.
Подведем итоги. Наши кнопки с иконками:
- Интерактивны ✅
- Управляются с клавиатуры ✅
- Доступны ✅
- Могут настраиваться ✅
Вы можете посмотреть весь код этого примера ниже, а также примеры других svg-иконок с ресурса codepen.io, как с масками, так и без.
Примеры SVG-иконок с Codepen
Пример из статьи
See the Pen SVG Icon by Elen (@ambassador) on CodePen.
Twitter Like Button
See the Pen Twitter Love Button by Álex S. Lérida (@lerida) on CodePen.
Социальные иконки с трансформацией и изменением фона при наведении на них
See the Pen Social Icons Splash Effect by Arafat Hussein (@rfthusn) on CodePen.
Набор простых SVG-иконок
See the Pen SVG By Hand by Tristan White (@triss90) on CodePen.
Анимация создания SVG-иконки
See the Pen SVG Heart Animation with CSS by Nikolay Talanov (@suez) on CodePen.
Динамическая маска при прокрутке контента
See the Pen Liquid masking - scroll by Cassie Evans (@cassie-codes) on CodePen.
Скачать множество SVG-иконок в различных размерах вы можете с сайта freeicons.io.