Градиентные границы в 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;
}
}

результат

Теги:
перевод, css

Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.