Создание компонентов пользовательского интерфейса с SVG и CSS

Создание компонентов пользовательского интерфейса с SVG и CSS

От автора: SVG — это не только иконки и иллюстрации, в нем есть множество скрытых возможностей, о которых разработчики иногда забывают. Существует множество вариантов, в которых использование SVG имеет больше смысла по сравнению с CSS.

Например, создание круговой анимации загрузки или применение масок к изображениям. Это не означает, что использование CSS в таких случаях невозможно, но иногда может быть сложно бороться с кроссбраузерными проблемами, основанными на используемой технике (например, масках), поэтому использование SVG может сэкономить время и усилия.

Отличительной особенностью SVG является то, что они могут быть отзывчивыми, производительными и готовыми работать с HTML и CSS. Моя цель в этой статье— познакомить вас с различными вариантами использования, в которых мы можем использовать SVG вместе с HTML и CSS для создания определенных компонентов пользовательского интерфейса. Давайте перейдем к вариантам использования. Вы готовы?

Cut-Out Avatar

Я заметил Cut-Out Avatar изучая CSS Facebook. В мессенджере аватарка пользователя может быть отмечена значком. Часть аватарки вырезается, чтобы выделить место для значка.

Создание компонентов пользовательского интерфейса с SVG и CSS

Это можно сделать, добавив белый border в CSS (как быстрое решение). Но почему бы не реализовать это в динамическом компоненте SVG?

.badge { border: 2px solid #ff;
}

Вы можете подумать, зачем использовать SVG, если border работает? Ну, здесь нет правильного или неправильного. Но есть решение, которое лучше другого. Вы помните, на уроках математики, когда учитель упоминал проблему, у нее могли быть разные решения, и одно из них могло быть лучшим с точки зрения гибкости? Я вижу то же самое для нашего случая.

В любом случае, я покажу вам, как решение с border может быстро сломаться:

При наведении: фон карты будет меняться, поэтому белая рамка будет казаться странной.

При использовании темного режима: белая рамка будет поверх черного фона.

Обратите внимание, как белая рамка значка пересекается с темным фоном а также при наведении:

Создание компонентов пользовательского интерфейса с SVG и CSS

Мы можем решить эту проблему, изменив цвет границы при наведении, но мне не кажется это лучшим решением.

.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 и CSS

Мы используем элемент SVG <image> для размещения аватарки. Чтобы вырезать область значка, нам нужно создать два элемента <circle>, один белый, а другой черный.

При использовании маски любой элемент с черной заливкой будет скрыт, а белый будет виден. Черный круг расположен в правом нижнем углу с радиусом 18. В инструментах дизайна это называется вычитанием. Мы хотим вычесть маленький круг из большего. Вот финальная демонстрация:

Раздел заголовка

В одном из моих клиентских проектов я создал раздел заголовка, объединив SVG и CSS.

Создание компонентов пользовательского интерфейса с SVG и CSS

Компонент должен работать с короткими и длинными заголовками, а если заголовок слишком длинный, он должен переноситься на несколько строк без нарушения макета. Чтобы осуществить это, я сделал следующее:

скопировал фиксированную часть (справа) и добавил ее как встроенный SVG.

использовал CSS для создания строки под заголовком, а также для маленьких кружков в начале и в конце строки.

построил макет компонента с помощью flexbox, чтобы избежать использования ненужного позиционирования.

Создание компонентов пользовательского интерфейса с SVG и CSS

Начнем с базовых 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;
}

Создание компонентов пользовательского интерфейса с SVG и CSS

Следующим шагом я хочу добавить границу под элементом <span>, чтобы имитировать соединенную линию с SVG.

Создание компонентов пользовательского интерфейса с SVG и CSS

Я заметил, что 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 и CSS

Подчеркивание пользовательских ссылок с помощью SVG

Мы можем использовать SVG для создания подчеркиваний пользовательских ссылок. Несколько лет назад я создал скрипт, который случайным образом генерирует path и перерисовывает его при наведении. Рассмотрим следующий рисунок для предварительного ознакомления до и после.

Создание компонентов пользовательского интерфейса с SVG и CSS

Идея состоит в том, что мы хотим вставить 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

Пользовательские ленты SVG

Во время работы над клиентским проектом мне понадобился способ прикрепить ленты к разделу таким образом, чтобы их можно было разместить где угодно с помощью CSS, и которые были бы достаточно динамичным, чтобы менять их цвет только с помощью одной переменной CSS. Рассмотрим следующий рисунок:

Создание компонентов пользовательского интерфейса с SVG и CSS

В Adobe Illustrator я разделил ленту на слои:

Базовый: принимает цвет заливки

Прозрачный черный: показывает более темные области

Прозрачный белый: показывает более светлые области.

Создание компонентов пользовательского интерфейса с SVG и CSS

Давайте посмотрим на код SVG.

<svg> <defs> <g id="tape" fill="currentColor"> <!-- path contents --> </g> </defs>
</svg>

Обратите внимание, что я добавил fill=currentColor. Ключевое слово currentColor наследует значение свойства CSS color, поэтому мы можем динамически изменять цвет, используя только одно свойство.

Учитывая, что у нас есть основа со сплошным цветом и два других слоя для светлых и темных областей, изменение цвета приведет к тому, что ленты будут выглядеть по-разному.

Создание компонентов пользовательского интерфейса с SVG и CSS

Более того, мы можем превратить 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, Яндекс.Дзен