CSS 可以将边界半径与具有渐变的边界图像一起使用吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5706963/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Possible to use border-radius together with a border-image which has a gradient?
提问by paulwilde
I'm styling an input field which has a rounded border (border-radius), and attempting to add a gradient to said border. I can successfully make the gradient and the rounded border, however neither work together. It's either rounded with no gradient, or a border with a gradient, but no rounded corners.
我正在设计一个具有圆形边框(边框半径)的输入字段,并尝试为所述边框添加渐变。我可以成功地制作渐变和圆角边框,但是两者都不能一起工作。它要么是没有渐变的圆角,要么是带有渐变但没有圆角的边框。
-webkit-border-radius: 5px;
-webkit-border-image: -webkit-gradient(linear, 0 0, 0 100%, from(#b0bbc4), to(#ced9de)) 1 100%;
Is there anyway to have both CSS properties work together, or is this not possible?
无论如何让两个 CSS 属性一起工作,或者这是不可能的?
采纳答案by Shauna
Probably not possible, as per the W3C spec:
根据 W3C 规范,可能不可能:
A box's backgrounds, but not its border-image, are clipped to the appropriate curve(as determined by ‘background-clip'). Other effects that clip to the border or padding edge (such as ‘overflow' other than ‘visible') also must clip to the curve. The content of replaced elements is always trimmed to the content edge curve. Also, the area outside the curve of the border edge does not accept mouse events on behalf of the element.
一个框的背景,而不是它的边框图像,被剪裁到适当的曲线(由'background-clip'确定)。裁剪到边框或填充边缘的其他效果(例如“溢出”而不是“可见”)也必须裁剪到曲线。替换元素的内容总是修剪到内容边缘曲线。另外,边框边缘曲线外的区域不接受代表元素的鼠标事件。
This is likely because border-image
can take some potentially complicated patterns. If you want a rounded, image border, you'll need to create one yourself.
这可能是因为border-image
可能采用一些潜在的复杂模式。如果你想要一个圆形的图像边框,你需要自己创建一个。
回答by Camilo Martin
This is possible, and it does not require extra markup, but uses an ::after
pseudo-element.
这是可能的,它不需要额外的标记,而是使用::after
伪元素。
It involves putting a pseudo-element with a gradient background below and clipping that. This works in all current browsers without vendor prefixes or hacks (even IE), but if you want to support vintage versions of IE, you should either consider solid color fallbacks, javascript, and/or custom MSIE CSS extensions (i.e., filter
, CSSPie-like vector trickery, etc).
它涉及在下方放置一个具有渐变背景的伪元素并对其进行剪辑。这适用于所有当前没有供应商前缀或黑客(甚至 IE)的浏览器,但如果您想支持 IE 的老式版本,您应该考虑纯色回退、javascript 和/或自定义 MSIE CSS 扩展(即filter
,CSSPie-像矢量诡计等)。
Here's a live example (jsfiddle version):
这是一个实时示例(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>
The extra styling above is to show:
上面的额外样式是为了显示:
- This works with any background
- It works just fine with
box-shadow
,inset
or not - Does not require you to add the shadow to the pseudo-element
- 这适用于任何背景
- 它适用于
box-shadow
,inset
或不适用 - 不需要您将阴影添加到伪元素
Again, this works with IE, Firefox and Webkit/Blink browsers.
同样,这适用于 IE、Firefox 和 Webkit/Blink 浏览器。
回答by theeastcoastwest
Working on this same problem. Came across a non-svg solution which is more succinct than others here:
正在处理同样的问题。在这里遇到了一个比其他人更简洁的非 svg 解决方案:
div{
width: 300px;
height: 80px;
border: double 1em transparent;
border-radius: 30px;
background-image: linear-gradient(white, white),
linear-gradient(to right, green, gold);
background-origin: border-box;
background-clip: content-box, border-box;
}
<div></div>
This is not my own solution and has been taken from here: https://gist.github.com/stereokai/36dc0095b9d24ce93b045e2ddc60d7a0
这不是我自己的解决方案,取自此处:https: //gist.github.com/stereokai/36dc0095b9d24ce93b045e2ddc60d7a0
回答by Vadim Ovchinnikov
I would use SVG for this:
我会为此使用 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 can be used as separate file (preferred way) or like part of value of background
(code below will work only in webkit-browsers):
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>
For this to work in MS Edge and Firefox we should escape our markup after utf8
, so we will be replacing double quotes "
with single quotes '
, #
with %23
and %
with %25
:
对于这个在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>
回答by chrichrichri
Solutions for transparentelements: working at least in Firefox.
透明元素的解决方案:至少在 Firefox 中工作。
There is actually one way I found without pseudo classes - but it only works for radial gradients:
实际上我发现了一种没有伪类的方法 - 但它只适用于径向渐变:
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>
Getting a transparent element with pseudo classes I only found this way - ok it is not a gradient, but it is at least a multicolored striped border (looking like life-rings):
使用伪类获取透明元素我只是通过这种方式找到的 - 好吧,它不是渐变,但它至少是一个多色条纹边框(看起来像救生圈):
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>
with a svg (most satisfying in terms of variability but needs most codelines too):
使用 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>
回答by Gerben
What if you apply the gradient to the background. Than and add an extra div inside, with margin set to the old border-width and with a white background, and of course a borderradius. That way you have the effect of a border, but are actually using background, which is clipped correctly.
如果将渐变应用于背景会怎样。然后在里面添加一个额外的 div,边距设置为旧的边框宽度和白色背景,当然还有边框半径。这样你就有了边框的效果,但实际上使用的是背景,它被正确剪裁。
回答by Becky Conning
This always works for me in WebKit, although its a bit tricky!
这在 WebKit 中总是对我有用,尽管它有点棘手!
Basically you just make the border bigger then mask it out with bigger and smaller pseudo-element's borders : ).
基本上你只是让边框变大,然后用越来越小的伪元素的边框来掩盖它:)。
.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;
}