Можно ли использовать border-radius вместе с border-image, у которого есть градиент? - PullRequest
56 голосов
/ 18 апреля 2011

Я оформляю поле ввода, которое имеет закругленную границу (border-radius), и пытаюсь добавить градиент к указанной границе. Я могу успешно сделать градиент и закругленную границу, однако ни то, ни другое не работает вместе. Он либо закругленный без градиента, либо граница с градиентом, но без закругленных углов.

-webkit-border-radius: 5px;
-webkit-border-image: -webkit-gradient(linear, 0 0, 0 100%, from(#b0bbc4), to(#ced9de)) 1 100%;

В любом случае, чтобы оба свойства CSS работали вместе или это невозможно?

Ответы [ 7 ]

86 голосов
/ 24 марта 2015

Это возможно, и не требует дополнительной разметки , но использует ::after псевдоэлемент .

screenshot

Это включает в себя размещение псевдоэлемента с градиентным фоном ниже и отсечение этого.Это работает во всех текущих браузерах без префиксов или хаков поставщиков (даже 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браузеры.

29 голосов
/ 18 апреля 2011

Вероятно, это невозможно, в соответствии со спецификацией W3C:

Фоны бокса, но не его изображение границы, обрезаются до соответствующей кривой (как определенофон-клип ').Другие эффекты, которые ограничивают границу или край заполнения (такие как «переполнение», отличное от «видимый»), также должны ограничиваться кривой.Содержимое замененных элементов всегда обрезается до кривой края содержимого.Кроме того, область за пределами кривой края границы не принимает события мыши от имени элемента.

Вероятно, это связано с тем, что border-image может принимать некоторые потенциально сложные шаблоны.Если вы хотите скруглить границу изображения, вам нужно создать ее самостоятельно.

8 голосов
/ 29 октября 2018

Работая над этой же проблемой, мы столкнулись с решением, отличным от 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

2 голосов
/ 08 марта 2018

Решения для прозрачных элементов: работает хотя бы в 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>
2 голосов
/ 22 июня 2017

Я бы использовал 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 (приведенный ниже код будет работать только в браузерах webkit):

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>
2 голосов
/ 12 ноября 2013

Это всегда работает для меня в 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;
}

http://plnkr.co/edit/luO6G95GtxdywZF0Qxf7?p=preview

2 голосов
/ 18 апреля 2011

Что, если вы примените градиент к фону.Затем добавьте дополнительный div внутри, с полем, установленным на старую ширину границы, с белым фоном и, конечно, borderradius.Таким образом, вы получаете эффект границы, но на самом деле используете фон, который правильно обрезается.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...