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

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

  • Для этого не существует простого и очевидного 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; /* !importante */
   border: solid $border transparent; /* !importante */
   border-radius: 1em;

   &:before {
      content: '';
      position: absolute;
      top: 0; right: 0; bottom: 0; left: 0;
      z-index: -1;
      margin: -$border; /* !importante */
      border-radius: inherit; /* !importante */
      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;
   }
}

результат

Комментарии (8)


  1. bezrukovyra
    24.01.2019 04:49

    Браузер Samsung на galaxy s9 не отображает, в Chrome нормально…


    1. lleo_aha
      24.01.2019 09:51
      +5

      Я бы все бы эти bixby, браузеры samsung и «используйте приложение Сообщения вместо приложения Сообщения» сложил бы в кучку и сжёг :) Единственный минус данного телефона (ну кроме цены ещё) я думаю :)


      1. Stepanow
        24.01.2019 11:57
        +3

        Так вроде телефоны Самсунг оснащены функцией сжигания?


        1. lleo_aha
          24.01.2019 17:41

          Исправили :) Но вот если серьёзно — у меня на телефоне есть 2 приложения «часы», 2 приложения «сообщения», 2 магазина приложений, 2 браузера и ещё много чего по 2. Причём самсунговские ещё и не удаляются на стандартной прошивке.

          Я думаю рано или поздно мобильные телефоны придут к чему то наподобие диалога установки браузеров в windows — включаешь новый телефон и оно тебя спрашивает что конкретно ставить


          1. Alex01d
            26.01.2019 08:38
            +1

            Попробуйте через adb shell удалить предустановленные, обычно помогает на Андроидах 5+


  1. ChieF_Of_ReD
    24.01.2019 18:41

    Вопрос, а что, чистый css без синтаксиса «sass» и «less» уже больше не котируется? По такой логике вы могли бы его еще сжать и обфусцировать.

    Второй пример не работает, хромиум, 55.


  1. PaulZi
    24.01.2019 19:02

    Всё это хорошо если только однородный фон без прозрачности…


  1. alexvoz
    24.01.2019 23:01

    Была как-то задача сверстать резиновый блок с градиентным бордером с закруглениями но с полу-прозрачной подложкой. Элемент-обертка не подходила.
    Пришлось сохранить рамку как картинку и использовать как заливку для бордера.
    Костыль выглядел примерно так codepen.io/alexvozn/pen/BModQg