Представим ситуацию: перед вами встало сверх задание — нужно сделать на сайте блок с градиентной обводкой. Нужно сразу понимать, что для этого не существует простого и очевидного CSS API. Это значит, что для получения необходимого визуального эффекта нам нужно писать определенные “костыли”. Предлагаю рассмотреть 2 подхода к решению этой задачи.
Автор статьи Gradient Borders in CSS Крис Койер предлагает пойти простым путем. Можно сделать “элемент-обертку” с линейно-градиентным фоном, а затем внутренним элементом заблокировать большую часть фона, кроме тонкой линии вокруг нее. Выглядеть это будет следующим образом:
![](https://habrastorage.org/getpro/habr/upload_files/417/d5e/3f0/417d5e3f0e2df7ddfd73d0c64f369e60.png)
Давайте пошагово разберем, что сделано в данном примере. У нас есть 2 блока — “обертка” и текст. “Обертке” задан градиент и без наложения второго блока она выглядит так:
![](https://habrastorage.org/getpro/habr/upload_files/a28/069/613/a2806961368dfce2693d45113645cc51.png)
Текстовый блок находиться внутри этой “обертки” и его фон такой же как и фон окружения. Какие проблемы из-за этого могут появиться?
Вот что будет, если внутреннему блоку не задать фон:
![](https://habrastorage.org/getpro/habr/upload_files/000/4aa/fca/0004aafcadfb24aa5ab605cf46723098.png)
А на следующем примере мы увидим, что будет, если внешний фон не совместим с внутренним:
![](https://habrastorage.org/getpro/habr/upload_files/30c/c2c/9c2/30cc2c9c247c18cb298db6ea23c8bc42.png)
Из этого может следовать вывод, что таким образом сделать прозрачную кнопку с градиентной обводкой попросту не получится.
Усложним себе задачу и попробуем сделать скругленные углы обводки. На примере от Криса Коера с этим нет проблем.
![](https://habrastorage.org/getpro/habr/upload_files/74c/881/f43/74c881f4300c33a7cb4a479f8a978be5.png)
Но рассмотрим этот же пример в более реалистичной среде. На одном из проектов, над которыми работает наша студия, нам нужно было создать кнопки-теги с обводкой всего в 1 px (на приведенном выше примере бордер толщиной в целых 5 px).
![](https://habrastorage.org/getpro/habr/upload_files/1b8/411/344/1b8411344177f5a35823209c041d5f99.png)
Этот пример достаточно показательный, ведь чаще всего обводка должна быть именно в 1 px. Тут врывается проблема с рендерингом браузера. Если настоящую обводку браузер почти всегда интерпретирует правильно (она всегда выглядит как 1 px вокруг блока), то данный подход такого не гарантирует. Если присмотреться — то обводка блоков в разных местах имеет разную ширину, и может меняться в зависимости от разрешения экрана. Когда элемент относительно маленький, то этого никто может и не заметить, но с большой красивой кнопкой с визуально разной шириной бордера сверху и снизу смириться будет сложно.
Еще одним минусом становится анимация градиента. Для обводки шириной в 1 px анимация будет выглядеть мгновенной. На полноценную анимацию может уйти уйма времени и нервных клеток программиста.
Рассмотрим второй подход к созданию градиентной обводки. В статье Как сделать border градиентом автор предлагает использовать достаточно хитрое свойство border-image-slice в сочетании с border-image:
![](https://habrastorage.org/getpro/habr/upload_files/2bf/89f/318/2bf89f318d52bf305a3099265e7365b8.png)
Эта техника позволяет делать настоящую обводку не только градиентом, но и изображением, которое будет корректно отображаться. При этом сам блок можно сделать даже прозрачным. Но проблема возникает, когда мы хотим применить радиус обводки.
Что же не так с этим моментом? Радиус попросту не применяется. То есть когда мы прописываем свойство CSS, то оно никак не влияет на отображение блока.
![](https://habrastorage.org/getpro/habr/upload_files/347/a06/2bc/347a062bc5594687279585ac7bcf6467.png)
И вот что мы получаем в результате:
![](https://habrastorage.org/getpro/habr/upload_files/d5d/9d6/6ab/d5d9d66abf443a4d6c911ce1d6cf94a1.png)
Дальше в статье приводится пример с закругленными углами. Здесь применяется такой же метод, как и в предыдущем примере — “блок-обертка” и блок с контентом, который его перекрывает.
Давайте подведем итоги этого разбора:
CSS на данный момент не предоставляет возможности сделать блок с градиентной обводкой, добавить ей закругленные углы и одновременно сделать блок прозрачным.
Если сделать блоки с градиентом обводкой в 1–2 px, то нужно быть готовым, что ширина этой обводки будет неравномерной.
Ограничения касаются только блоков с градиентной обводкой и радиусом бордера.
Вместо заключения
Стоит упомянуть, что достаточно проблематично анимировать бордеры с градиентом. Такие моменты нужно обсуждать заранее и при возможности отбросить их необходимость. Вместо этого можно сделать внешнюю анимацию — добавление тени, смещение блока и т.д. Также если кто-то предложит вам вставить кнопку картинкой, смело отметайте этот ужасный вариант. Для каждой кнопки нужна будет отдельная картинка, текст в ней изменить нельзя и их вес на порядок больше, чем у реализации кодом. Это все скажется на скорости работы страницы, работы с ее админкой и на будущей поддержке сайта.
sfi0zy
Да, проблема округлений и сглаживаний — это головная боль, причем не только в вопросах бордеров, это вообще много где может проявиться. А вот по поводу «сверх задания» — у нас рано или поздно появится поддержка CSS Painting API во всех браузерах, и можно будет посмотреть на эту задачу с новой стороны. Ну или уже сейчас забить на это API и руками воткнуть канвасы везде. Это не так производительно, но любые кривые, градиенты, да что угодно — в нашем распоряжении. Нарисовать можно все, что угодно, вопрос времени. Для особых извращений можно использовать WebGL контекст и делать разные волны по этим бордерам при наведении, но это уже совсем другая история. А пока вот концепт (не протестированный) крокодильчиков для вдохновения: