Градиентные границы в CSS

Доброго времени суток уважаемые хабровчане. Представляю вашему вниманию перевод статьи Криса Коера.

Допустим, вам нужна градиентная граница вокруг определенного элемента. И вы, такой, думаете:

  • Для этого не существует простого и очевидного CSS API.
  • Я просто сделаю элемент-обертку с линейно-градиентным фоном, а затем внутренний элемент заблокирует большую часть этого фона, за исключением тонкой линии заполнения вокруг него.

Выглядеть это будет как-то так:

HTML

<div class="module-border-wrap"><div class="module">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Vero pariatur corporis quaerat voluptatum eos tempora temporibus nisi voluptates sed, exercitationem sequi dolore culpa incidunt accusamus, quasi unde reprehenderit ea molestias.
</div></div>

SCSS

body {
   height: 100vh;
   margin: 0;
   display: grid;
   place-items: center;
   background: #222;
}

.module-border-wrap {
   max-width: 250px;
   padding: 1rem;
   position: relative;
   background: linear-gradient(to right, red, purple);
   padding: 3px;
}

.module {
   background: #222;
   color: white;
   padding: 2rem;
}

результат


Если вам не нравится идея оберточного элемента, вы можете использовать псевдоэлемент, до тех пор, пока отрицательное значение z-индекса в порядке (этого не произошло бы, если бы было много вложений родительских элементов с их собственными фонами).

Вот пример Стивена Шоу, закрепляющий border-radius:

HTML

<div class="gradient-box">

<p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent bibendum, lorem vel tincidunt imperdiet, nibh elit laoreet felis, a bibendum nisl tortor non orci. Donec pretium fermentum felis, quis aliquet est rutrum ut. Integer quis massa ut lacus viverra pharetra in eu lacus. Aliquam tempus odio adipiscing diam pellentesque rhoncus. Curabitur a bibendum est. </p>

</div>

SCSS

.gradient-box {

   display: flex;
   align-items: center;
   //width: 50vw;
   width: 90%;
   margin: auto;
   max-width: 22em;

   position: relative;
   padding: 30% 2em;
   box-sizing: border-box;

   $border: 5px;
   color: #FFF;
   background: #000;
   background-clip: padding-box; /* !importanté */
   border: solid $border transparent; /* !importanté */
   border-radius: 1em;

   &:before {
      content: '';
      position: absolute;
      top: 0; right: 0; bottom: 0; left: 0;
      z-index: -1;
      margin: -$border; /* !importanté */
      border-radius: inherit; /* !importanté */
      background: linear-gradient(to right, red, orange);
   }
}

html { height: 100%; background: #000; display: flex; }
body { margin: auto; }

результат

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

HTML

<div class="module">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Vero pariatur corporis quaerat voluptatum eos tempora temporibus nisi voluptates sed, exercitationem sequi dolore culpa incidunt accusamus, quasi unde reprehenderit ea molestias.
</div>

CSS

body {
   height: 100vh;
   margin: 0;
   display: grid;
   place-items: center;
   background: #222;
}

.module {
   max-width: 250px;
   padding: 1rem;
   color: white;
   border-width: 3px;
   border-style: solid;
   border-image: 
      linear-gradient(
         to bottom, 
         red, 
         rgba(0, 0, 0, 0)
      ) 1 100%;
}

результат

Использование как border-image, так и border-image-slice, вероятно, является самым простым синтаксисом для создания градиентной границы, но, к сожалению, это просто несовместимо с border-radius.

HTML

<div>

   <div class="on-light">
      <button class="border-gradient border-gradient-purple">
         I have a gradient
      </button>
   </div>

   <div class="on-dark">
      <button class="border-gradient border-gradient-purple">
         I have a gradient
      </button>
   </div>

   <div class="on-light">
      <button class="border-gradient border-gradient-green">
         I have a gradient
      </button>
   </div>

   <div class="on-dark">
      <button class="border-gradient border-gradient-green">
         I have a gradient
      </button>
   </div>

</div>

SCSS

button {
   background: none;
   text-decoration: inherit;
   font-family: system-ui;
   font-size: 1rem;
   padding: 1rem 2rem;
}

.border-gradient {
   border-image-slice: 1;
   border-width: 2px;
}
.border-gradient-purple {
   border-image: linear-gradient(to left, #743ad5, #d53a9d);
}
.border-gradient-green {
   border-image: linear-gradient(to left, #00C853, #B2FF59);
}

body {
   height: 100vh;
   margin: 0;
   display: flex;
   justify-content: center;
   align-items: center;
   > div {
      width: 100%;
      text-align: center;
   }
   > div > div {
      width: 100%;
      padding: 1rem;
   }
}

.on-dark {
   background: #222;
   button {
      color: white;
   }
}

результат
Поделиться публикацией

Похожие публикации

Комментарии 12

    0
    Браузер Samsung на galaxy s9 не отображает, в Chrome нормально…
      +6
      Я бы все бы эти bixby, браузеры samsung и «используйте приложение Сообщения вместо приложения Сообщения» сложил бы в кучку и сжёг :) Единственный минус данного телефона (ну кроме цены ещё) я думаю :)
        +7
        Так вроде телефоны Самсунг оснащены функцией сжигания?
          0
          Исправили :) Но вот если серьёзно — у меня на телефоне есть 2 приложения «часы», 2 приложения «сообщения», 2 магазина приложений, 2 браузера и ещё много чего по 2. Причём самсунговские ещё и не удаляются на стандартной прошивке.

          Я думаю рано или поздно мобильные телефоны придут к чему то наподобие диалога установки браузеров в windows — включаешь новый телефон и оно тебя спрашивает что конкретно ставить
            +1
            Попробуйте через adb shell удалить предустановленные, обычно помогает на Андроидах 5+
          0
          >браузеры samsung

          Самсунгобраузер, на самом деле, вполне себе Chrome, просто немного допиленный, и он таки обновляется по мере обновления самого Chrome, не особенно отставая от оригинала. Но в отличие от последнего позволяет использовать блокировщики рекламы, что ценно.

          И Chrome, во избежание дублирования приложений, с самсунгофона, насколько это позволяет утверждать мой личный опыт, штатно выпиливается — при этом вместо него автоматически устанавливается Android System WebView, но это нужный компонент, который, как я понял, используется разными приложениями, которым может потребоваться отображать веб-контент.
            0
            ну вот простейший пример плохой функциональности — хром умеет следить когда скачанные файлы пропадают (уведомление о скачанном файле исчезает само), самсунгобраузер — нет, и таких мелочей очень много
        +1
        Вопрос, а что, чистый css без синтаксиса «sass» и «less» уже больше не котируется? По такой логике вы могли бы его еще сжать и обфусцировать.

        Второй пример не работает, хромиум, 55.
          0
          Всё это хорошо если только однородный фон без прозрачности…
            0
            В таком случае можно сделать 4 элемента: верхний и нижний двухпиксельные блоки с градиентом, левый и правый разных цветов. Так можно делать с небольшими рассчетами градиент не только под 90 градусов.
            Но это напоминает верстку скругленных углов во времена IE6.
            Разумеется, это кроссбраузерное решение. Можно css clip, думаю или другими инструментами такое реализовать.
            0
            Была как-то задача сверстать резиновый блок с градиентным бордером с закруглениями но с полу-прозрачной подложкой. Элемент-обертка не подходила.
            Пришлось сохранить рамку как картинку и использовать как заливку для бордера.
            Костыль выглядел примерно так codepen.io/alexvozn/pen/BModQg
              0
              Всё новое, хорошо забытое старое? :)

            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

            Самое читаемое