От автора: SVG — это не только иконки и иллюстрации, в нем есть множество скрытых возможностей, о которых разработчики иногда забывают. Существует множество вариантов, в которых использование SVG имеет больше смысла по сравнению с CSS.
Например, создание круговой анимации загрузки или применение масок к изображениям. Это не означает, что использование CSS в таких случаях невозможно, но иногда может быть сложно бороться с кроссбраузерными проблемами, основанными на используемой технике (например, масках), поэтому использование SVG может сэкономить время и усилия.
Отличительной особенностью SVG является то, что они могут быть отзывчивыми, производительными и готовыми работать с HTML и CSS. Моя цель в этой статье— познакомить вас с различными вариантами использования, в которых мы можем использовать SVG вместе с HTML и CSS для создания определенных компонентов пользовательского интерфейса. Давайте перейдем к вариантам использования. Вы готовы?
Cut-Out Avatar
Я заметил Cut-Out Avatar изучая CSS Facebook. В мессенджере аватарка пользователя может быть отмечена значком. Часть аватарки вырезается, чтобы выделить место для значка.
Это можно сделать, добавив белый border в CSS (как быстрое решение). Но почему бы не реализовать это в динамическом компоненте SVG?
.badge { border: 2px solid #ff; }
Вы можете подумать, зачем использовать SVG, если border работает? Ну, здесь нет правильного или неправильного. Но есть решение, которое лучше другого. Вы помните, на уроках математики, когда учитель упоминал проблему, у нее могли быть разные решения, и одно из них могло быть лучшим с точки зрения гибкости? Я вижу то же самое для нашего случая.
В любом случае, я покажу вам, как решение с border может быстро сломаться:
При наведении: фон карты будет меняться, поэтому белая рамка будет казаться странной.
При использовании темного режима: белая рамка будет поверх черного фона.
Обратите внимание, как белая рамка значка пересекается с темным фоном а также при наведении:
Мы можем решить эту проблему, изменив цвет границы при наведении, но мне не кажется это лучшим решением.
.card__badge { border: 2px solid #ff; } .card:hover .card__badge { border-color: lightgrey; } @media (prefers-color-scheme: dark) { .card__badge { border-color: #454545; } }
С SVG вышеперечисленное можно решить гораздо лучше, вырезав область под значком. Таким образом, это решение будет работать с любым фоном. Рассмотрим следующий рисунок:
Мы используем элемент SVG <image> для размещения аватарки. Чтобы вырезать область значка, нам нужно создать два элемента <circle>, один белый, а другой черный.
При использовании маски любой элемент с черной заливкой будет скрыт, а белый будет виден. Черный круг расположен в правом нижнем углу с радиусом 18. В инструментах дизайна это называется вычитанием. Мы хотим вычесть маленький круг из большего. Вот финальная демонстрация:
Раздел заголовка
В одном из моих клиентских проектов я создал раздел заголовка, объединив SVG и CSS.
Компонент должен работать с короткими и длинными заголовками, а если заголовок слишком длинный, он должен переноситься на несколько строк без нарушения макета. Чтобы осуществить это, я сделал следующее:
скопировал фиксированную часть (справа) и добавил ее как встроенный SVG.
использовал CSS для создания строки под заголовком, а также для маленьких кружков в начале и в конце строки.
построил макет компонента с помощью flexbox, чтобы избежать использования ненужного позиционирования.
Начнем с базовых HTML и CSS.
<h2 class="c-section__title"> <span>CSS is awesome</span> <svg xmlns="http://www.w3.org/2000/svg" width="128" height="34.5" viewBox="0 0 128 34.5" preserveAspectRatio="none"> <path fill="none" stroke="#d8d8d8" stroke-width="2" d="M127 1H33.5L1 33.5"></path> </svg> </h2>
.c-section__title { max-width: 700px; width: fit-content; display: flex; margin-left: auto; margin-right: auto; }
Следующим шагом я хочу добавить границу под элементом <span>, чтобы имитировать соединенную линию с SVG.
Я заметил, что SVG никак не связан со строкой. Поскольку мы используем flexbox, исправить это несложно. Нам просто нужно выровнять flex-элементы по flex-end.
.c-section__title { max-width: 700px; width: fit-content; display: flex; align-items: flex-end; margin-left: auto; margin-right: auto; }
Затем нам нужно добавить кружки в начале и в конце, используя псевдоэлементы с абсолютным позиционированием.
Что еще хорошо в использовании SVG, так это то, что мы можем превратить SVG path в пунктирную линию, которую можно анимировать. Для этого нам нужно убедиться, что экспортируемый path в SVG не обведен.
<path d="M127 1H33.5L1 33.5" fill="none" stroke="#d8d8d8" stroke-width="2"></path>
Идея в том, чтобы получить длину нашего path. В Chrome DevTools выберите элемент <path>, вы увидите == $0 в конце элемента. Оставьте его выбранным и напишите в консоли следующий скрипт:
$0.getTotalLength() // 139.46
$0 — это быстрый способ выбрать элемент из DOM, не вдаваясь в нечто подобное:
let sectionPath = document.querySelector('#path'); console.log(sectionPath.getTotalLength());
Это был быстрый совет в контексте данного примера. Теперь, когда у нас есть длина, мы можем делать с ней все, что захотим. Например, мы можем анимировать path при наведении.
.c-section__title--dashed path { stroke-dasharray: 139; stroke-dashoffset: 0; transition: 0.7s; } .c-section__title--dashed:hover path { stroke-dashoffset: 139; }
Или мы можем просто превратить его в пунктирную линию (в этом случае нам не нужно знать длину path).
Подчеркивание пользовательских ссылок с помощью SVG
Мы можем использовать SVG для создания подчеркиваний пользовательских ссылок. Несколько лет назад я создал скрипт, который случайным образом генерирует path и перерисовывает его при наведении. Рассмотрим следующий рисунок для предварительного ознакомления до и после.
Идея состоит в том, что мы хотим вставить SVG в каждую ссылку, и это будет выглядеть следующим образом:
<svg width="400" height="35" xmlns="http://www.w3.org/2000/svg"> <path id="pathItem" d="M5 5 Q 30 15 170 5" stroke="black" fill="transparent" stroke-width="7" stroke-linecap="round"/> </svg>
Волшебство происходит путем изменения значения атрибута d. Вот изображение, показывающее, как на самом деле рисуется path.
Пользовательские ленты SVG
Во время работы над клиентским проектом мне понадобился способ прикрепить ленты к разделу таким образом, чтобы их можно было разместить где угодно с помощью CSS, и которые были бы достаточно динамичным, чтобы менять их цвет только с помощью одной переменной CSS. Рассмотрим следующий рисунок:
В Adobe Illustrator я разделил ленту на слои:
Базовый: принимает цвет заливки
Прозрачный черный: показывает более темные области
Прозрачный белый: показывает более светлые области.
Давайте посмотрим на код SVG.
<svg> <defs> <g id="tape" fill="currentColor"> <!-- path contents --> </g> </defs> </svg>
Обратите внимание, что я добавил fill=currentColor. Ключевое слово currentColor наследует значение свойства CSS color, поэтому мы можем динамически изменять цвет, используя только одно свойство.
Учитывая, что у нас есть основа со сплошным цветом и два других слоя для светлых и темных областей, изменение цвета приведет к тому, что ленты будут выглядеть по-разному.
Более того, мы можем превратить SVG в шаблон и использовать элемент SVG <use> для повторного использования ленты без дублирования SVG.
<svg style="display: none;"> <defs> <g id="tape" fill="currentColor"> <!-- path contents --> </g> </defs> </svg> <!-- An example of using the tape from a template --> <svg class="tape" style="--angle: 10deg; color: red; --size: 120px;" aria-hidden="true" focusable="false" viewBox="0 0 123 47"> <use href="#tape"></use> </svg>
Обратите внимание, как я добавил ленту с помощью элемента <use>. Что в этом хорошего, так это использование переменных CSS в качестве встроенных стилей. Вот как выглядит CSS:
.tape { width: var(--size); transform: rotate(var(--angle)); }
Заключение
Создание компонентов пользовательского интерфейса с помощью SVG может упростить задачу. Использование SVG для некоторых компонентов пользовательского интерфейса может не быть на 100% идеальным вариантом, но это зависит от контекста проекта, над которым вы работаете.
Автор: Ahmad Shadeed
Источник: ishadeed.com
Редакция: Команда webformyself.
Читайте нас в Telegram, VK, Яндекс.Дзен