Можно ли использовать border-radius вместе с border-image, у которого есть градиент?
Я стилизую поле ввода, которое имеет закругленную границу (border-radius), и пытаюсь добавить градиент к указанной границе. Я могу успешно сделать градиент и закругленную границу, однако ни одна из них не работает вместе. Он либо закругленный без градиента, либо граница с градиентом, но без закругленных углов.
-webkit-border-radius: 5px;
-webkit-border-image: -webkit-gradient(linear, 0 0, 0 100%, from(#b0bbc4), to(#ced9de)) 1 100%;
В любом случае, чтобы оба свойства CSS работали вместе, или это невозможно?
14 ответов
Вероятно, не возможно, согласно спецификации W3C:
Фоны бокса, но не его обрамление, обрезаются до соответствующей кривой (как определено в "background-clip"). Другие эффекты, которые ограничивают границу или край заполнения (например, "переполнение", отличное от "видимый"), также должны ограничиваться кривой. Содержимое замененных элементов всегда обрезается до кривой края содержимого. Кроме того, область за пределами кривой края границы не принимает события мыши от имени элемента.
Это, вероятно, потому что border-image
может принять некоторые потенциально сложные шаблоны. Если вы хотите скругленную границу изображения, вам нужно создать ее самостоятельно.
Работая над этой же проблемой, мы столкнулись с решением, отличным от svg, которое более лаконично, чем другие:
.rounded-color-border-element{
width: 300px;
height: 80px;
border: double 4px transparent;
border-radius: 80px;
background-image: linear-gradient(white, white), radial-gradient(circle at top left, #f00,#3020ff);
background-origin: border-box;
background-clip: content-box, border-box;
}
Это не мое собственное решение, оно было взято отсюда: https://gist.github.com/stereokai/36dc0095b9d24ce93b045e2ddc60d7a0
Это возможно и не требует дополнительной разметки, но использует ::after
псевдоэлемент.
Это включает в себя размещение псевдоэлемента с градиентным фоном ниже и отсечение. Это работает во всех текущих браузерах без префиксов или хаков поставщиков (даже IE), но если вы хотите поддерживать старинные версии IE, вам следует рассмотреть возможность использования однотонных запасных вариантов, javascript и / или пользовательских расширений MSIE CSS (т. Е. filter
CSSPie-подобные векторные трюки и т. Д.).
Вот живой пример ( версия jsfiddle):
@import url('//raw.githubusercontent.com/necolas/normalize.css/master/normalize.css');
html {
/* just for showing that background doesn't need to be solid */
background: linear-gradient(to right, #DDD 0%, #FFF 50%, #DDD 100%);
padding: 10px;
}
.grounded-radiants {
position: relative;
border: 4px solid transparent;
border-radius: 16px;
background: linear-gradient(orange, violet);
background-clip: padding-box;
padding: 10px;
/* just to show box-shadow still works fine */
box-shadow: 0 3px 9px black, inset 0 0 9px white;
}
.grounded-radiants::after {
position: absolute;
top: -4px; bottom: -4px;
left: -4px; right: -4px;
background: linear-gradient(red, blue);
content: '';
z-index: -1;
border-radius: 16px;
}
<p class="grounded-radiants">
Some text is here.<br/>
There's even a line break!<br/>
so cool.
</p>
Дополнительный стиль выше, чтобы показать:
- Это работает с любым фоном
- Работает с
box-shadow
,inset
или нет - Не требует добавления тени к псевдоэлементу
Опять же, это работает с браузерами IE, Firefox и Webkit/Blink.
Теперь мы можем использовать маску, чтобы легко добиться этого, сохраняя при этом прозрачность и отзывчивость.
Подробнее: https://dev.to/afif/border-with-gradient-and-radius-387f
Я бы использовал SVG для этого:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 220 220" width="100%" height="100%" preserveAspectRatio="none">
<defs>
<linearGradient id="gradient">
<stop offset="0" style="stop-color:#0070d8" />
<stop offset="0.5" style="stop-color:#2cdbf1" />
<stop offset="1" style="stop-color:#83eb8a" />
</linearGradient>
</defs>
<ellipse ry="100" rx="100" cy="110" cx="110" style="fill:none;stroke:url(#gradient);stroke-width:6;" />
</svg>
SVG может использоваться как отдельный файл (предпочтительный способ) или как часть значения background
(приведенный ниже код будет работать только в веб-браузерах):
div {
width: 250px;
height: 250px;
background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 220 220" width="100%" height="100%" preserveAspectRatio="none"><defs><linearGradient id="gradient"><stop offset="0" style="stop-color:#0070d8" /><stop offset="0.5" style="stop-color:#2cdbf1" /><stop offset="1" style="stop-color:#83eb8a" /></linearGradient></defs><ellipse ry="100" rx="100" cy="110" cx="110" style="fill:none;stroke:url(#gradient);stroke-width:6;" /></svg>');
}
<div></div>
Для того, чтобы это работало в MS Edge и Firefox, мы должны избежать нашей разметки после utf8
поэтому мы будем заменять двойные кавычки "
с одинарными кавычками '
, #
с %23
а также %
с %25
:
div {
width: 250px;
height: 250px;
background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 220 220' width='100%25' height='100%25' preserveAspectRatio='none'><defs><linearGradient id='gradient'><stop offset='0' style='stop-color:%230070d8' /><stop offset='0.5' style='stop-color:%232cdbf1' /><stop offset='1' style='stop-color:%2383eb8a' /></linearGradient></defs><ellipse ry='100' rx='100' cy='110' cx='110' style='fill:none;stroke:url(%23gradient);stroke-width:6;' /></svg>");
background-size: 100% 100%; /* Fix for Fifefox image scaling */
}
<div></div>
Решения для прозрачных элементов: работаем хотя бы в Firefox.
На самом деле есть один способ, который я нашел без псевдо-классов - но он работает только для радиальных градиентов:
body {
background: linear-gradient(white, black), -moz-linear-gradient(white, black), -webkit-linear-gradient(white, black);
height: 300px;
}
div{
text-align: center;
width: 100px;
height: 100px;
font-size:30px;
color: lightgrey;
border-radius: 80px;
color: transparent;
background-clip: border-box, text;
-moz-background-clip: border-box, text;
-webkit-background-clip: border-box, text;
background-image: radial-gradient(circle,
transparent, transparent 57%, yellow 58%, red 100%), repeating-linear-gradient(-40deg, yellow,
yellow 10%, orange 21%, orange 30%, yellow 41%);
line-height: 100px;
}
<body>
<div class="radial-gradient"> OK </div>
</body>
Получая прозрачный элемент с псевдо-классами, я нашел только этот способ - хорошо, это не градиент, а по крайней мере разноцветная полосатая рамка (похожая на кольца жизни):
body {
background: linear-gradient(white, black, white);
height: 600px;
}
div{
position: absolute;
width: 100px;
height: 100px;
font-size:30px;
background-color:transparent;
border-radius:80px;
border: 10px dashed orange;
color: transparent;
background-clip: text;
-moz-background-clip: text;
-webkit-background-clip: text;
background-image: repeating-linear-gradient(-40deg, yellow,
yellow 10%, orange 11%, orange 20%, yellow 21%);
text-align:center;
line-height:100px;
}
div::after {
position: absolute;
top: -10px; bottom: -10px;
left: -10px; right: -10px;
border: 10px solid yellow;
content: '';
z-index: -1;
border-radius: 80px;
}
<body>
<div class="gradient"> OK </div>
</body>
с SVG (наиболее удовлетворительным с точки зрения изменчивости, но также нуждается в большинстве строк кода):
body{
margin: 0;
padding: 0;
}
div {
position: absolute;
display: flex;
align-items: center;
left: 50%;
transform: translateX(-50%);
text-align: center;
}
span {
position: absolute;
left: 50%;
transform: translateX(-50%);
width: 100px;
height: 100px;
line-height: 105px;
font-size:40px;
background-clip: text;
-moz-background-clip: text;
-webkit-background-clip: text;
background-image: repeating-linear-gradient(-40deg, yellow,
yellow 10%, orange 11%, orange 20%, yellow 21%);
color: transparent;
}
svg {
fill: transparent;
stroke-width: 10px;
stroke:url(#gradient);
}
<head>
</head>
<body>
<div>
<span>OK</span>
<svg>
<circle class="stroke-1" cx="50%" cy="50%" r="50"/>
<defs>
<linearGradient id="gradient" x1="0%" y1="0%" x2="0%" y2="15%" gradientTransform="rotate(-40)" spreadMethod="reflect">
<stop offset="0%" stop-color="orange" />
<stop offset="49%" stop-color="orange" />
<stop offset="50%" stop-color="yellow" />
<stop offset="99%" stop-color="yellow" />
</linearGradient>
</defs>
</svg>
</div>
</body>
Это всегда работает для меня в WebKit, хотя это немного сложно!
По сути, вы просто увеличиваете границу, а затем маскируете ее границами псевдоэлемента большего и меньшего размера:).
.thing {
display: block;
position: absolute;
left: 50px;
top: 50px;
margin-top: 18pt;
padding-left: 50pt;
padding-right: 50pt;
padding-top: 25pt;
padding-bottom: 25pt;
border-radius: 6px;
font-size: 18pt;
background-color: transparent;
border-width: 3pt;
border-image: linear-gradient(#D9421C, #E8A22F) 14% stretch;
}
.thing::after {
content: '';
border-radius: 8px;
border: 3pt solid #fff;
width: calc(100% + 6pt);
height: calc(100% + 6pt);
position: absolute;
top: -6pt;
left: -6pt;
z-index: 900;
}
.thing::before {
content: '';
border-radius: 2px;
border: 1.5pt solid #fff;
width: calc(100%);
height: calc(100% + 0.25pt);
position: absolute;
top: -1.5pt;
left: -1.5pt;
z-index: 900;
}
Что делать, если вы примените градиент к фону. Затем добавьте дополнительный div внутри, с полем, установленным для старой ширины границы, с белым фоном, и, конечно, с borderradius. Таким образом, вы получаете эффект границы, но на самом деле используете фон, который обрезается правильно.
Ответ прост: чтобы иметь цветную изогнутую границу, нам сначала нужно иметь изогнутый фон. Тогда ваша проблема будет решена (без градиентной ситуации):
.buttonBorder {
-fx-border-color: red;
-fx-background-color: white;
-fx-background-radius: 30;
-fx-border-radius: 30;
}
Решение для градиентной границы.
Этот код отлично работает для меня!
Вы можете использовать свойство clip-path CSS.
.rounded-border-image {
--border-image: linear-gradient(to bottom, orange, skyblue, magenta);
--border-radius: 4px;
background-image: var(--border-image);
background-origin: border-box;
border-color: transparent;
border-radius: var(--border-radius);
border-style: solid;
border-width: 4px;
clip-path: inset(0% 0% 0% 0% round var(--border-radius));
}
Что выглядит примерно так при использовании вокругimg
элемент простого красного изображения размером 40x40.
Надеюсь это поможет!
Эта альтернатива довольно новая: https://github.com/bfintal/jQuery.IE9Gradius.js
Просто включите скрипт last в тег head, и он должен обработать все остальное. См readme заметки