Create gradient border button with trasparency? [duplicate] - css

I have the following CSS:
a.btn.white-grad {
background: $lgrey;
color: #313149 !important;
border: 1px solid #000;
border-image-source: linear-gradient(to right, #9c20aa, #fb3570);
border-image-slice: 20;
float: left;
#include font-size(26);
margin: 75px 0;
}
Adding border-radius: 5px doesn't seem to do anything. I figured it's because I'm using a border gradient... is there a way for me to achieve the desired 5px border radius at all?

2021: I recommend using the CSS mask method since the support is pretty good now
You cannot use border-radius with gradient. Here is another idea where you can rely on multiple background and adjust the background-clip:
.white-grad {
background:
linear-gradient(#ccc 0 0) padding-box, /*this is your grey background*/
linear-gradient(to right, #9c20aa, #fb3570) border-box;
color: #313149;
padding: 10px;
border: 5px solid transparent;
border-radius: 15px;
display: inline-block;
margin: 75px 0;
}
<div class="white-grad"> Some text here</div>
<div class="white-grad"> Some long long long text here</div>
<div class="white-grad"> Some long long <br>long text here</div>
SVG method
If you want transparency, you can consider SVG like below:
svg {
width:200px;
height:100px;
margin:10px;
}
<svg xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="Gradient" x1="0" x2="100" y1="0" y2="0" gradientUnits="userSpaceOnUse">
<stop stop-color="#9c20aa" offset="0"/>
<stop stop-color="#fb3570" offset="1"/>
</linearGradient>
</defs>
<rect x="5" y="5" height="100%" width="100%" style="width:calc(100% - 10px);height:calc(100% - 10px)" rx="20" ry="20" stroke-width="10" fill="transparent" stroke="url(#Gradient)"/>
</svg>
That you can apply as background:
.white-grad {
background:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" ><defs><linearGradient id="Gradient" x1="0" x2="100" y1="0" y2="0" gradientUnits="userSpaceOnUse"><stop stop-color="%239c20aa" offset="0"/><stop stop-color="%23fb3570" offset="1"/></linearGradient></defs><rect x="5" y="5" width="100%" height="100%" style="height:calc(100% - 10px);width:calc(100% - 10px)" rx="20" ry="20" stroke-width="10" fill="transparent" stroke="url(%23Gradient)"/></svg>');
color: #313149;
padding:25px;
border-radius:15px;
display:inline-block;
margin: 75px 0;
}
body {
background:yellow;
}
<div class="white-grad"> Some text here</div>
<div class="white-grad"> text very loooooooooooong here</div>
And the same way as mask where you can get the gradient outside of the SVG:
.white-grad {
color: #313149;
padding: 25px;
border-radius: 15px;
display: inline-block;
margin: 75px 0;
background-size: 0 0;
position: relative;
z-index: 0;
}
.white-grad::before {
content: "";
position: absolute;
z-index: -1;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-image: inherit;
background-size: auto;
--mask: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" ><rect x="5" y="5" width="100%" height="100%" style="height:calc(100% - 10px);width:calc(100% - 10px)" rx="20" ry="20" stroke-width="10" fill="transparent" stroke="white"/></svg>');
-webkit-mask: var(--mask);
mask: var(--mask);
}
body {
background: yellow;
}
<div class="white-grad" style="background-image:linear-gradient(to right,blue,red)"> Some text here</div>
<div class="white-grad" style="background-image:linear-gradient(black,lightblue,green)"> text very loooooooooooong here</div>
<div class="white-grad" style="background-image:radial-gradient(blue,pink)"> text very<br> loooooooooooong here</div>
You can also use it as common element and consider position:absolute to place it around the text:
.white-grad {
color: #313149;
padding: 25px;
border-radius: 15px;
display: inline-block;
margin: 75px 0;
position:relative;
z-index:0;
}
.white-grad > svg {
position:absolute;
top:0;
left:0;
height:100%;
width:100%;
z-index:-1;
}
body {
background: yellow;
}
.hide {
height:0;
width:0;
}
<svg class="hide" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="Gradient" x1="0" x2="100" y1="0" y2="0" gradientUnits="userSpaceOnUse"><stop stop-color="#9c20aa" offset="0"/><stop stop-color="#fb3570" offset="1"/></linearGradient></defs><rect x="5" y="5" width="100%" height="100%" id="border" style="height:calc(100% - 10px);width:calc(100% - 10px)" rx="20" ry="20" stroke-width="10" fill="transparent" stroke="url(#Gradient)"/></svg>
<div class="white-grad">
<svg xmlns="http://www.w3.org/2000/svg">
<use href="#border" />
</svg>
Some text here</div>
<div class="white-grad">
<svg xmlns="http://www.w3.org/2000/svg">
<use href="#border" />
</svg>
text very loooooooooooong here</div>
CSS Mask method
Here is a different idea with CSS using mask where you will have transparency and it will also be responsive:
.white-grad {
color: #313149;
padding: 10px;
display: inline-block;
margin: 75px 0;
position: relative;
z-index: 0;
}
.white-grad:before {
content: "";
position: absolute;
z-index: -1;
inset: 0;
padding: 5px;
border-radius: 15px;
background: linear-gradient(to right, #9c20aa, #fb3570);
-webkit-mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
}
<div class="white-grad"> Some text here</div>
<div class="white-grad"> Some long long long text here</div>
<div class="white-grad"> Some long long <br>long text here</div>
With CSS variables, we can make it easy to adjust:
.white-grad {
--b:5px; /* border width*/
--r:15px; /* the radius */
color: #313149;
padding: calc(var(--b) + 5px);
display: inline-block;
margin: 75px 0;
position:relative;
z-index:0;
}
.white-grad:before {
content: "";
position: absolute;
z-index: -1;
inset: 0;
padding: var(--b);
border-radius: var(--r);
background: var(--c,linear-gradient(to right, #9c20aa, #fb3570));
-webkit-mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
}
body {
background:#f2f2f2;
}
<div class="white-grad"> Some text here</div>
<div class="white-grad" style="--r:20px;--b:10px;--c:linear-gradient(140deg,red,yellow,green)"> Some long long long text here</div>
<div class="white-grad" style="--r:30px;--b:8px;--c:linear-gradient(-40deg,black 50%,blue 0)"> Some long long <br>long text here</div>
<div class="white-grad" style="--r:40px;--b:20px;--c:conic-gradient(black,orange,purple)"> Some long long <br>long text here<br> more and more more and more</div>
Related question to get a different effect: How do you apply a gradient from outer to inner, only to borders, in CSS?
The above examples cover also the circle shape:
.white-grad {
--b:5px; /* border width*/
color: #313149;
display: inline-block;
margin: 10px;
width: 150px;
aspect-ratio: 1;
position: relative;
z-index: 0;
}
.white-grad:before {
content:"";
position:absolute;
z-index:-1;
inset: 0;
background: var(--c,linear-gradient(to right, #9c20aa, #fb3570));
padding: var(--b);
border-radius: 50%;
-webkit-mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
}
body {
background:#f2f2f2;
}
<div class="white-grad"></div>
<div class="white-grad" style="--b:10px;--c:linear-gradient(140deg,red,yellow,green)"></div>
<div class="white-grad" style="--b:8px;--c:linear-gradient(-40deg,black 50%,blue 0)"></div>
<div class="white-grad" style="--b:20px;--c:conic-gradient(black,orange,purple)"></div>
Related question in case you want to apply an animation to the border: Button with transparent background and rotating gradient border
Also different radius shapes:
.white-grad {
--b:5px; /* border width*/
color: #313149;
display: inline-block;
margin: 10px;
width: 150px;
aspect-ratio: 1;
position: relative;
z-index: 0;
}
.white-grad:before {
content: "";
position: absolute;
z-index: -1;
inset: 0;
background: var(--c,linear-gradient(to right, #9c20aa, #fb3570));
padding: var(--b);
border-radius: var(--r,50%);
-webkit-mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
}
body {
background:#f2f2f2;
}
<div class="white-grad" style="--r:50% 0 50% 50%;"></div>
<div class="white-grad" style="--b:10px;--r:50% 0;--c:linear-gradient(140deg,red,yellow,green)"></div>
<div class="white-grad" style="--b:8px;--r:50% 0 0;--c:linear-gradient(-40deg,black 50%,blue 0)"></div>
<div class="white-grad" style="--b:20px;--r:50% 50% 0 0;--c:conic-gradient(black,orange,purple)"></div>
and different border thickness:
.white-grad {
--b:5px; /* border width*/
color: #313149;
display: inline-block;
margin: 10px;
width: 150px;
aspect-ratio: 1;
position: relative;
z-index: 0;
}
.white-grad:before {
content: "";
position: absolute;
z-index: -1;
inset: 0;
background: var(--c,linear-gradient(#9c20aa, #fb3570));
padding: var(--b);
border-radius:var(--r,50%);
-webkit-mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
}
body {
background:#f2f2f2;
}
<div class="white-grad" style="--b:0 0 20px 20px;--r:50% 0 50% 50%;"></div>
<div class="white-grad" style="--b:10px 0 10px 0;--r:50% 0;--c:linear-gradient(140deg,red,yellow,green)"></div>
<div class="white-grad" style="--b:8px 0px 0px 8px;--r:50% 0 0;--c:linear-gradient(40deg,black 50%,blue 0)"></div>
<div class="white-grad" style="--b:20px 20px 0 20px;--r:50% 50% 0 0;--c:conic-gradient(pink,orange,red,pink)"></div>

You need to wrap the button in a div and set the border-radius on that parent div. In order to work, you will have to set overflow:hidden to that parent div as well. Like so:
.btn-wrap {
border-radius: 5px;
overflow: hidden;
margin: 20px;
width: 60px;
}
a.btn.white-grad {
background: #eee;
color: #313149 !important;
border: 20px solid #000;
border-image-source: linear-gradient(to right, #9c20aa, #fb3570);
border-image-slice: 20;
line-height: 2;
}
<div class="btn-wrap">
link
</div>

Related

Border image bug in Safari / on iOS [duplicate]

I have the following CSS:
a.btn.white-grad {
background: $lgrey;
color: #313149 !important;
border: 1px solid #000;
border-image-source: linear-gradient(to right, #9c20aa, #fb3570);
border-image-slice: 20;
float: left;
#include font-size(26);
margin: 75px 0;
}
Adding border-radius: 5px doesn't seem to do anything. I figured it's because I'm using a border gradient... is there a way for me to achieve the desired 5px border radius at all?
2021: I recommend using the CSS mask method since the support is pretty good now
You cannot use border-radius with gradient. Here is another idea where you can rely on multiple background and adjust the background-clip:
.white-grad {
background:
linear-gradient(#ccc 0 0) padding-box, /*this is your grey background*/
linear-gradient(to right, #9c20aa, #fb3570) border-box;
color: #313149;
padding: 10px;
border: 5px solid transparent;
border-radius: 15px;
display: inline-block;
margin: 75px 0;
}
<div class="white-grad"> Some text here</div>
<div class="white-grad"> Some long long long text here</div>
<div class="white-grad"> Some long long <br>long text here</div>
SVG method
If you want transparency, you can consider SVG like below:
svg {
width:200px;
height:100px;
margin:10px;
}
<svg xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="Gradient" x1="0" x2="100" y1="0" y2="0" gradientUnits="userSpaceOnUse">
<stop stop-color="#9c20aa" offset="0"/>
<stop stop-color="#fb3570" offset="1"/>
</linearGradient>
</defs>
<rect x="5" y="5" height="100%" width="100%" style="width:calc(100% - 10px);height:calc(100% - 10px)" rx="20" ry="20" stroke-width="10" fill="transparent" stroke="url(#Gradient)"/>
</svg>
That you can apply as background:
.white-grad {
background:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" ><defs><linearGradient id="Gradient" x1="0" x2="100" y1="0" y2="0" gradientUnits="userSpaceOnUse"><stop stop-color="%239c20aa" offset="0"/><stop stop-color="%23fb3570" offset="1"/></linearGradient></defs><rect x="5" y="5" width="100%" height="100%" style="height:calc(100% - 10px);width:calc(100% - 10px)" rx="20" ry="20" stroke-width="10" fill="transparent" stroke="url(%23Gradient)"/></svg>');
color: #313149;
padding:25px;
border-radius:15px;
display:inline-block;
margin: 75px 0;
}
body {
background:yellow;
}
<div class="white-grad"> Some text here</div>
<div class="white-grad"> text very loooooooooooong here</div>
And the same way as mask where you can get the gradient outside of the SVG:
.white-grad {
color: #313149;
padding: 25px;
border-radius: 15px;
display: inline-block;
margin: 75px 0;
background-size: 0 0;
position: relative;
z-index: 0;
}
.white-grad::before {
content: "";
position: absolute;
z-index: -1;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-image: inherit;
background-size: auto;
--mask: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" ><rect x="5" y="5" width="100%" height="100%" style="height:calc(100% - 10px);width:calc(100% - 10px)" rx="20" ry="20" stroke-width="10" fill="transparent" stroke="white"/></svg>');
-webkit-mask: var(--mask);
mask: var(--mask);
}
body {
background: yellow;
}
<div class="white-grad" style="background-image:linear-gradient(to right,blue,red)"> Some text here</div>
<div class="white-grad" style="background-image:linear-gradient(black,lightblue,green)"> text very loooooooooooong here</div>
<div class="white-grad" style="background-image:radial-gradient(blue,pink)"> text very<br> loooooooooooong here</div>
You can also use it as common element and consider position:absolute to place it around the text:
.white-grad {
color: #313149;
padding: 25px;
border-radius: 15px;
display: inline-block;
margin: 75px 0;
position:relative;
z-index:0;
}
.white-grad > svg {
position:absolute;
top:0;
left:0;
height:100%;
width:100%;
z-index:-1;
}
body {
background: yellow;
}
.hide {
height:0;
width:0;
}
<svg class="hide" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="Gradient" x1="0" x2="100" y1="0" y2="0" gradientUnits="userSpaceOnUse"><stop stop-color="#9c20aa" offset="0"/><stop stop-color="#fb3570" offset="1"/></linearGradient></defs><rect x="5" y="5" width="100%" height="100%" id="border" style="height:calc(100% - 10px);width:calc(100% - 10px)" rx="20" ry="20" stroke-width="10" fill="transparent" stroke="url(#Gradient)"/></svg>
<div class="white-grad">
<svg xmlns="http://www.w3.org/2000/svg">
<use href="#border" />
</svg>
Some text here</div>
<div class="white-grad">
<svg xmlns="http://www.w3.org/2000/svg">
<use href="#border" />
</svg>
text very loooooooooooong here</div>
CSS Mask method
Here is a different idea with CSS using mask where you will have transparency and it will also be responsive:
.white-grad {
color: #313149;
padding: 10px;
display: inline-block;
margin: 75px 0;
position: relative;
z-index: 0;
}
.white-grad:before {
content: "";
position: absolute;
z-index: -1;
inset: 0;
padding: 5px;
border-radius: 15px;
background: linear-gradient(to right, #9c20aa, #fb3570);
-webkit-mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
}
<div class="white-grad"> Some text here</div>
<div class="white-grad"> Some long long long text here</div>
<div class="white-grad"> Some long long <br>long text here</div>
With CSS variables, we can make it easy to adjust:
.white-grad {
--b:5px; /* border width*/
--r:15px; /* the radius */
color: #313149;
padding: calc(var(--b) + 5px);
display: inline-block;
margin: 75px 0;
position:relative;
z-index:0;
}
.white-grad:before {
content: "";
position: absolute;
z-index: -1;
inset: 0;
padding: var(--b);
border-radius: var(--r);
background: var(--c,linear-gradient(to right, #9c20aa, #fb3570));
-webkit-mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
}
body {
background:#f2f2f2;
}
<div class="white-grad"> Some text here</div>
<div class="white-grad" style="--r:20px;--b:10px;--c:linear-gradient(140deg,red,yellow,green)"> Some long long long text here</div>
<div class="white-grad" style="--r:30px;--b:8px;--c:linear-gradient(-40deg,black 50%,blue 0)"> Some long long <br>long text here</div>
<div class="white-grad" style="--r:40px;--b:20px;--c:conic-gradient(black,orange,purple)"> Some long long <br>long text here<br> more and more more and more</div>
Related question to get a different effect: How do you apply a gradient from outer to inner, only to borders, in CSS?
The above examples cover also the circle shape:
.white-grad {
--b:5px; /* border width*/
color: #313149;
display: inline-block;
margin: 10px;
width: 150px;
aspect-ratio: 1;
position: relative;
z-index: 0;
}
.white-grad:before {
content:"";
position:absolute;
z-index:-1;
inset: 0;
background: var(--c,linear-gradient(to right, #9c20aa, #fb3570));
padding: var(--b);
border-radius: 50%;
-webkit-mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
}
body {
background:#f2f2f2;
}
<div class="white-grad"></div>
<div class="white-grad" style="--b:10px;--c:linear-gradient(140deg,red,yellow,green)"></div>
<div class="white-grad" style="--b:8px;--c:linear-gradient(-40deg,black 50%,blue 0)"></div>
<div class="white-grad" style="--b:20px;--c:conic-gradient(black,orange,purple)"></div>
Related question in case you want to apply an animation to the border: Button with transparent background and rotating gradient border
Also different radius shapes:
.white-grad {
--b:5px; /* border width*/
color: #313149;
display: inline-block;
margin: 10px;
width: 150px;
aspect-ratio: 1;
position: relative;
z-index: 0;
}
.white-grad:before {
content: "";
position: absolute;
z-index: -1;
inset: 0;
background: var(--c,linear-gradient(to right, #9c20aa, #fb3570));
padding: var(--b);
border-radius: var(--r,50%);
-webkit-mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
}
body {
background:#f2f2f2;
}
<div class="white-grad" style="--r:50% 0 50% 50%;"></div>
<div class="white-grad" style="--b:10px;--r:50% 0;--c:linear-gradient(140deg,red,yellow,green)"></div>
<div class="white-grad" style="--b:8px;--r:50% 0 0;--c:linear-gradient(-40deg,black 50%,blue 0)"></div>
<div class="white-grad" style="--b:20px;--r:50% 50% 0 0;--c:conic-gradient(black,orange,purple)"></div>
and different border thickness:
.white-grad {
--b:5px; /* border width*/
color: #313149;
display: inline-block;
margin: 10px;
width: 150px;
aspect-ratio: 1;
position: relative;
z-index: 0;
}
.white-grad:before {
content: "";
position: absolute;
z-index: -1;
inset: 0;
background: var(--c,linear-gradient(#9c20aa, #fb3570));
padding: var(--b);
border-radius:var(--r,50%);
-webkit-mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
}
body {
background:#f2f2f2;
}
<div class="white-grad" style="--b:0 0 20px 20px;--r:50% 0 50% 50%;"></div>
<div class="white-grad" style="--b:10px 0 10px 0;--r:50% 0;--c:linear-gradient(140deg,red,yellow,green)"></div>
<div class="white-grad" style="--b:8px 0px 0px 8px;--r:50% 0 0;--c:linear-gradient(40deg,black 50%,blue 0)"></div>
<div class="white-grad" style="--b:20px 20px 0 20px;--r:50% 50% 0 0;--c:conic-gradient(pink,orange,red,pink)"></div>
You need to wrap the button in a div and set the border-radius on that parent div. In order to work, you will have to set overflow:hidden to that parent div as well. Like so:
.btn-wrap {
border-radius: 5px;
overflow: hidden;
margin: 20px;
width: 60px;
}
a.btn.white-grad {
background: #eee;
color: #313149 !important;
border: 20px solid #000;
border-image-source: linear-gradient(to right, #9c20aa, #fb3570);
border-image-slice: 20;
line-height: 2;
}
<div class="btn-wrap">
link
</div>

The border-image-source property showing black border with linear gredient [duplicate]

I have the following CSS:
a.btn.white-grad {
background: $lgrey;
color: #313149 !important;
border: 1px solid #000;
border-image-source: linear-gradient(to right, #9c20aa, #fb3570);
border-image-slice: 20;
float: left;
#include font-size(26);
margin: 75px 0;
}
Adding border-radius: 5px doesn't seem to do anything. I figured it's because I'm using a border gradient... is there a way for me to achieve the desired 5px border radius at all?
2021: I recommend using the CSS mask method since the support is pretty good now
You cannot use border-radius with gradient. Here is another idea where you can rely on multiple background and adjust the background-clip:
.white-grad {
background:
linear-gradient(#ccc 0 0) padding-box, /*this is your grey background*/
linear-gradient(to right, #9c20aa, #fb3570) border-box;
color: #313149;
padding: 10px;
border: 5px solid transparent;
border-radius: 15px;
display: inline-block;
margin: 75px 0;
}
<div class="white-grad"> Some text here</div>
<div class="white-grad"> Some long long long text here</div>
<div class="white-grad"> Some long long <br>long text here</div>
SVG method
If you want transparency, you can consider SVG like below:
svg {
width:200px;
height:100px;
margin:10px;
}
<svg xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="Gradient" x1="0" x2="100" y1="0" y2="0" gradientUnits="userSpaceOnUse">
<stop stop-color="#9c20aa" offset="0"/>
<stop stop-color="#fb3570" offset="1"/>
</linearGradient>
</defs>
<rect x="5" y="5" height="100%" width="100%" style="width:calc(100% - 10px);height:calc(100% - 10px)" rx="20" ry="20" stroke-width="10" fill="transparent" stroke="url(#Gradient)"/>
</svg>
That you can apply as background:
.white-grad {
background:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" ><defs><linearGradient id="Gradient" x1="0" x2="100" y1="0" y2="0" gradientUnits="userSpaceOnUse"><stop stop-color="%239c20aa" offset="0"/><stop stop-color="%23fb3570" offset="1"/></linearGradient></defs><rect x="5" y="5" width="100%" height="100%" style="height:calc(100% - 10px);width:calc(100% - 10px)" rx="20" ry="20" stroke-width="10" fill="transparent" stroke="url(%23Gradient)"/></svg>');
color: #313149;
padding:25px;
border-radius:15px;
display:inline-block;
margin: 75px 0;
}
body {
background:yellow;
}
<div class="white-grad"> Some text here</div>
<div class="white-grad"> text very loooooooooooong here</div>
And the same way as mask where you can get the gradient outside of the SVG:
.white-grad {
color: #313149;
padding: 25px;
border-radius: 15px;
display: inline-block;
margin: 75px 0;
background-size: 0 0;
position: relative;
z-index: 0;
}
.white-grad::before {
content: "";
position: absolute;
z-index: -1;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-image: inherit;
background-size: auto;
--mask: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" ><rect x="5" y="5" width="100%" height="100%" style="height:calc(100% - 10px);width:calc(100% - 10px)" rx="20" ry="20" stroke-width="10" fill="transparent" stroke="white"/></svg>');
-webkit-mask: var(--mask);
mask: var(--mask);
}
body {
background: yellow;
}
<div class="white-grad" style="background-image:linear-gradient(to right,blue,red)"> Some text here</div>
<div class="white-grad" style="background-image:linear-gradient(black,lightblue,green)"> text very loooooooooooong here</div>
<div class="white-grad" style="background-image:radial-gradient(blue,pink)"> text very<br> loooooooooooong here</div>
You can also use it as common element and consider position:absolute to place it around the text:
.white-grad {
color: #313149;
padding: 25px;
border-radius: 15px;
display: inline-block;
margin: 75px 0;
position:relative;
z-index:0;
}
.white-grad > svg {
position:absolute;
top:0;
left:0;
height:100%;
width:100%;
z-index:-1;
}
body {
background: yellow;
}
.hide {
height:0;
width:0;
}
<svg class="hide" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="Gradient" x1="0" x2="100" y1="0" y2="0" gradientUnits="userSpaceOnUse"><stop stop-color="#9c20aa" offset="0"/><stop stop-color="#fb3570" offset="1"/></linearGradient></defs><rect x="5" y="5" width="100%" height="100%" id="border" style="height:calc(100% - 10px);width:calc(100% - 10px)" rx="20" ry="20" stroke-width="10" fill="transparent" stroke="url(#Gradient)"/></svg>
<div class="white-grad">
<svg xmlns="http://www.w3.org/2000/svg">
<use href="#border" />
</svg>
Some text here</div>
<div class="white-grad">
<svg xmlns="http://www.w3.org/2000/svg">
<use href="#border" />
</svg>
text very loooooooooooong here</div>
CSS Mask method
Here is a different idea with CSS using mask where you will have transparency and it will also be responsive:
.white-grad {
color: #313149;
padding: 10px;
display: inline-block;
margin: 75px 0;
position: relative;
z-index: 0;
}
.white-grad:before {
content: "";
position: absolute;
z-index: -1;
inset: 0;
padding: 5px;
border-radius: 15px;
background: linear-gradient(to right, #9c20aa, #fb3570);
-webkit-mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
}
<div class="white-grad"> Some text here</div>
<div class="white-grad"> Some long long long text here</div>
<div class="white-grad"> Some long long <br>long text here</div>
With CSS variables, we can make it easy to adjust:
.white-grad {
--b:5px; /* border width*/
--r:15px; /* the radius */
color: #313149;
padding: calc(var(--b) + 5px);
display: inline-block;
margin: 75px 0;
position:relative;
z-index:0;
}
.white-grad:before {
content: "";
position: absolute;
z-index: -1;
inset: 0;
padding: var(--b);
border-radius: var(--r);
background: var(--c,linear-gradient(to right, #9c20aa, #fb3570));
-webkit-mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
}
body {
background:#f2f2f2;
}
<div class="white-grad"> Some text here</div>
<div class="white-grad" style="--r:20px;--b:10px;--c:linear-gradient(140deg,red,yellow,green)"> Some long long long text here</div>
<div class="white-grad" style="--r:30px;--b:8px;--c:linear-gradient(-40deg,black 50%,blue 0)"> Some long long <br>long text here</div>
<div class="white-grad" style="--r:40px;--b:20px;--c:conic-gradient(black,orange,purple)"> Some long long <br>long text here<br> more and more more and more</div>
Related question to get a different effect: How do you apply a gradient from outer to inner, only to borders, in CSS?
The above examples cover also the circle shape:
.white-grad {
--b:5px; /* border width*/
color: #313149;
display: inline-block;
margin: 10px;
width: 150px;
aspect-ratio: 1;
position: relative;
z-index: 0;
}
.white-grad:before {
content:"";
position:absolute;
z-index:-1;
inset: 0;
background: var(--c,linear-gradient(to right, #9c20aa, #fb3570));
padding: var(--b);
border-radius: 50%;
-webkit-mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
}
body {
background:#f2f2f2;
}
<div class="white-grad"></div>
<div class="white-grad" style="--b:10px;--c:linear-gradient(140deg,red,yellow,green)"></div>
<div class="white-grad" style="--b:8px;--c:linear-gradient(-40deg,black 50%,blue 0)"></div>
<div class="white-grad" style="--b:20px;--c:conic-gradient(black,orange,purple)"></div>
Related question in case you want to apply an animation to the border: Button with transparent background and rotating gradient border
Also different radius shapes:
.white-grad {
--b:5px; /* border width*/
color: #313149;
display: inline-block;
margin: 10px;
width: 150px;
aspect-ratio: 1;
position: relative;
z-index: 0;
}
.white-grad:before {
content: "";
position: absolute;
z-index: -1;
inset: 0;
background: var(--c,linear-gradient(to right, #9c20aa, #fb3570));
padding: var(--b);
border-radius: var(--r,50%);
-webkit-mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
}
body {
background:#f2f2f2;
}
<div class="white-grad" style="--r:50% 0 50% 50%;"></div>
<div class="white-grad" style="--b:10px;--r:50% 0;--c:linear-gradient(140deg,red,yellow,green)"></div>
<div class="white-grad" style="--b:8px;--r:50% 0 0;--c:linear-gradient(-40deg,black 50%,blue 0)"></div>
<div class="white-grad" style="--b:20px;--r:50% 50% 0 0;--c:conic-gradient(black,orange,purple)"></div>
and different border thickness:
.white-grad {
--b:5px; /* border width*/
color: #313149;
display: inline-block;
margin: 10px;
width: 150px;
aspect-ratio: 1;
position: relative;
z-index: 0;
}
.white-grad:before {
content: "";
position: absolute;
z-index: -1;
inset: 0;
background: var(--c,linear-gradient(#9c20aa, #fb3570));
padding: var(--b);
border-radius:var(--r,50%);
-webkit-mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
}
body {
background:#f2f2f2;
}
<div class="white-grad" style="--b:0 0 20px 20px;--r:50% 0 50% 50%;"></div>
<div class="white-grad" style="--b:10px 0 10px 0;--r:50% 0;--c:linear-gradient(140deg,red,yellow,green)"></div>
<div class="white-grad" style="--b:8px 0px 0px 8px;--r:50% 0 0;--c:linear-gradient(40deg,black 50%,blue 0)"></div>
<div class="white-grad" style="--b:20px 20px 0 20px;--r:50% 50% 0 0;--c:conic-gradient(pink,orange,red,pink)"></div>
You need to wrap the button in a div and set the border-radius on that parent div. In order to work, you will have to set overflow:hidden to that parent div as well. Like so:
.btn-wrap {
border-radius: 5px;
overflow: hidden;
margin: 20px;
width: 60px;
}
a.btn.white-grad {
background: #eee;
color: #313149 !important;
border: 20px solid #000;
border-image-source: linear-gradient(to right, #9c20aa, #fb3570);
border-image-slice: 20;
line-height: 2;
}
<div class="btn-wrap">
link
</div>

How to create rounded borders with gap?

I'm trying to create blocks and elements with rounded corners and a gap between the corner and the straight line. Turns out its a little bit difficult :)
I also have to create "button" like this,
and
If I can not create them in pure CSS I will use svg for this, but I have to solve the above problem first.
Anyone have some idea?
Looks like a job for a border-image.
const grab = document.getElementById('grab');
console.log("url('data:image/svg+xml;base64,"+btoa(grab.innerHTML.replace(/\r?\n */g,''))+"')");
.border-gap {
border: 16px solid;
border-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0OCA0OCI+PHBhdGggc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIGZpbGw9Im5vbmUiIGQ9Ik0xLDEzIEExMiwxMiAwIDAgMSAxMywxTTE5LDEgSDI5TTM1LDEgQTEyLDEyIDAgMCAxIDQ3LDEzTTQ3LDE5IFYyOU00NywzNSBBMTIsMTIgMCAwIDEgMzUsNDdNMjksNDcgSDE5TTEzLDQ3IEExMiwxMiAwIDAgMSAxLDM1TTEsMjkgVjE5Ij48L3BhdGg+PC9zdmc+') calc(100% * 19 / 48);
padding: 8px;
}
<div class="border-gap">Text</div>
<template id="grab">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
<path stroke="black" stroke-width="2" stroke-linecap="round" fill="none" d="
M1,13 A12,12 0 0 1 13,1
M19,1 H29
M35,1 A12,12 0 0 1 47,13
M47,19 V29
M47,35 A12,12 0 0 1 35,47
M29,47 H19
M13,47 A12,12 0 0 1 1,35
M1,29 V19
" />
</svg>
</template>
I've included the SVG I used as well as the method for getting a data: URL for it, which can then be put in the border-image.
mask can help you:
.box {
--r:40px; /* radius*/
--g:5px; /* gap */
width:200px;
height:100px;
display:inline-block;
border:5px solid red;
box-sizing:border-box;
margin:10px;
border-radius:var(--r);
--m:#0000 90deg,#000 0;
-webkit-mask:
conic-gradient(from -180deg at calc(100% - var(--g)) var(--g) ,var(--m))
0 100%/var(--r) var(--r),
conic-gradient(from 90deg at var(--g) var(--g) ,var(--m))
100% 100%/var(--r) var(--r),
conic-gradient(from 0deg at var(--g) calc(100% - var(--g)),var(--m))
100% 0 /var(--r) var(--r),
conic-gradient(from -90deg at calc(100% - var(--g)) calc(100% - var(--g)),var(--m))
0 0 /var(--r) var(--r),
linear-gradient(#000 0 0);
-webkit-mask-repeat:no-repeat;
-webkit-mask-composite:xor;
mask-composite:exclude;
}
<div class="box"></div>
<div class="box" style="width:100px;--r:50px"></div>
<div class="box" style="width:150px;--r:50px"></div>
To have content, use it as pseudo element:
.box {
--r:30px; /* radius*/
--g:5px; /* gap */
width:200px;
height:100px;
display:inline-block;
box-sizing:border-box;
padding:20px;
position:relative;
margin:10px;
}
.box:before {
content:"";
position:absolute;
inset:0;
border:5px solid red;
border-radius:var(--r);
--m:#0000 90deg,#000 0;
-webkit-mask:
conic-gradient(from -180deg at calc(100% - var(--g)) var(--g) ,var(--m))
0 100%/var(--r) var(--r),
conic-gradient(from 90deg at var(--g) var(--g) ,var(--m))
100% 100%/var(--r) var(--r),
conic-gradient(from 0deg at var(--g) calc(100% - var(--g)),var(--m))
100% 0 /var(--r) var(--r),
conic-gradient(from -90deg at calc(100% - var(--g)) calc(100% - var(--g)),var(--m))
0 0 /var(--r) var(--r),
linear-gradient(#000 0 0);
-webkit-mask-repeat:no-repeat;
-webkit-mask-composite:xor;
mask-composite:exclude;
}
<div class="box"> content </div>
<div class="box" style="width:100px;--r:50px">content </div>
<div class="box" style="width:150px;--r:50px">content </div>
The hard way...
body {
background: #232323;
}
.btn {
border: 3px solid #fafafa;
padding: 2px 12px;
border-radius: 50%;
background: transparent;
position: relative;
}
.btn::before,
.btn::after {
position: absolute;
content: '';
width: 3px;
height: 5px;
background: #232323;
top: 40%
}
.btn::before {
left: -10%;
}
.btn::after {
right: -8%;
}
.btn:hover {
border-color: #ff3844
}
.btn:hover .icon {
color: #ff3844
}
.icon {
color: #fafafa;
font-size: 1.5rem;
font-weight: bold
}
span {
position: relative
}
span::before,
span::after {
position: absolute;
content: '';
width: 5px;
height: 4px;
background: #232323;
left: -2px;
}
span::before {
top: -22px
}
span::after {
bottom: -2px
}
<button class="btn">
<div class='icon'>+</div>
<span></span>
</button>

Repeating SVG Pattern as a Clip Path for Border using ::after pseudo element

I'm trying to create an asymmetrical sawtooth pattern at the bottom of a site header that looks like this (except the sawtooth would be asymmetrical):
sawtooth border example
I've tried some pure CSS approaches using (linear-gradient) to no avail.
I can create a repeating pattern, but cannot also make it a clip-path such that it cuts out the background color of the header (pink) to show the body background underneath.
https://codepen.io/rasterisk/pen/rZrKNO
body {
background-color: tomato;
margin: 0;
}
.header {
position:relative;
height: 100px;
background-color: pink;
overflow: hidden;
margin: 0;
}
.header svg {
position: absolute;
bottom: 0;
}
div::after { /*this doesn't work*/
content:'';
height:12px;
width: 100%;
position: absolute;
background-color: green;
-webkit-clip-path: url(#svgPath);
clip-path: url(#svgPath);
bottom: 0;
margin: 0;
}
<body>
<div class="header">
<svg width="3000" height="11" xmlns="http://www.w3.org/2000/svg">
<defs>
<clipPath id="svgPath">
<pattern id="Pattern" x="0" y="0" width="20" height="12" patternUnits="userSpaceOnUse">
<path fill="" d="M-131-167l-144.42-104.93s-6.87-4.59-9.07 3.17c-2.11 7.48-13.93 83.86-16.69 101.76H-131zM-354-50l-.14 111s15.54-94.28 17.65-101.76c2.19-7.77 9.07-3.17 9.07-3.17L-183 61V-50h-171zM0 0v11.61S2.08 1.73 2.33.92C2.6.07 3.04.5 3.04.5L20 11.61V0H0z"/>
</pattern>
</clipPath>
</defs>
<rect fill="url(#Pattern)" width="2400" height="12"/>
</svg>
</div>
</body>
Any help would be appreciated. This degree of SVG control is new terrain for me.
body {
background-color: tomato;
margin: 0;
}
.header {
position:relative;
height: 100px;
background-color: pink;
overflow: hidden;
margin: 0;
}
.header svg {
position: absolute;
bottom: 0;
background-color: tomato;//set your svg background color as your body color
}
div::after { /*this doesn't work*/
content:'';
height:12px;
width: 100%;
position: absolute;
background-color: green;
-webkit-clip-path: url(#svgPath);
clip-path: url(#svgPath);
bottom: 0;
margin: 0;
}
<body>
<div class="header">
<svg width="3000" height="11" xmlns="http://www.w3.org/2000/svg">
<defs>
<clipPath id="svgPath">
<pattern id="Pattern" x="0" y="0" width="20" height="12" patternUnits="userSpaceOnUse">
<path fill="" d="M-131-167l-144.42-104.93s-6.87-4.59-9.07 3.17c-2.11 7.48-13.93 83.86-16.69 101.76H-131zM-354-50l-.14 111s15.54-94.28 17.65-101.76c2.19-7.77 9.07-3.17 9.07-3.17L-183 61V-50h-171zM0 0v11.61S2.08 1.73 2.33.92C2.6.07 3.04.5 3.04.5L20 11.61V0H0z"/>
</pattern>
</clipPath>
</defs>
<rect fill="url(#Pattern)" width="2400" height="12"/>
</svg>
</div>
</body>
You may try this css only solution: css linear gradients
body {
background-color: tomato;
margin: 0;
}
.header {
position:relative;
height: 100px;
background-color: pink;
overflow: hidden;
margin: 0;
}
.header svg {
position: absolute;
bottom: 0;
}
div::after{
content:"";
display:block;
position:absolute;
bottom:0;
width:100%;
height:1.2em;
background-image:-webkit-linear-gradient(45deg, pink 25%, transparent 26%, transparent 75%, pink 75%),
-webkit-linear-gradient(135deg, pink 25%, tomato 26%,tomato 75%, pink 75%);
background-image: linear-gradient(45deg, pink 25%, transparent 26%, transparent 75%, pink 75%),
linear-gradient(135deg, pink 25%, tomato 26%, tomato 75%, pink 75%);
background-size:36px 36px;}
}
<body>
<div class="header">
</div>
</body>
UPDATE
an asymmetrical sawtooth pattern:
body {
background-color: tomato;
margin: 0;
}
.header {
position:relative;
height: 100px;
background-color: pink;
overflow: hidden;
margin: 0;
}
.header svg {
position: absolute;
bottom: 0;
}
div::after{
content:"";
display:block;
position:absolute;
bottom:0;
width:100%;
height:25px;
background-image: linear-gradient(45deg, tomato 50%, pink 50% , pink 100%),
linear-gradient(135deg, tomato 50%, pink 50% , pink 100%);
background-size:25px 25px;}
}
<body>
<div class="header">
</div>
</body>

Border Gradient with Border Radius

I have the following CSS:
a.btn.white-grad {
background: $lgrey;
color: #313149 !important;
border: 1px solid #000;
border-image-source: linear-gradient(to right, #9c20aa, #fb3570);
border-image-slice: 20;
float: left;
#include font-size(26);
margin: 75px 0;
}
Adding border-radius: 5px doesn't seem to do anything. I figured it's because I'm using a border gradient... is there a way for me to achieve the desired 5px border radius at all?
2021: I recommend using the CSS mask method since the support is pretty good now
You cannot use border-radius with gradient. Here is another idea where you can rely on multiple background and adjust the background-clip:
.white-grad {
background:
linear-gradient(#ccc 0 0) padding-box, /*this is your grey background*/
linear-gradient(to right, #9c20aa, #fb3570) border-box;
color: #313149;
padding: 10px;
border: 5px solid transparent;
border-radius: 15px;
display: inline-block;
margin: 75px 0;
}
<div class="white-grad"> Some text here</div>
<div class="white-grad"> Some long long long text here</div>
<div class="white-grad"> Some long long <br>long text here</div>
SVG method
If you want transparency, you can consider SVG like below:
svg {
width:200px;
height:100px;
margin:10px;
}
<svg xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="Gradient" x1="0" x2="100" y1="0" y2="0" gradientUnits="userSpaceOnUse">
<stop stop-color="#9c20aa" offset="0"/>
<stop stop-color="#fb3570" offset="1"/>
</linearGradient>
</defs>
<rect x="5" y="5" height="100%" width="100%" style="width:calc(100% - 10px);height:calc(100% - 10px)" rx="20" ry="20" stroke-width="10" fill="transparent" stroke="url(#Gradient)"/>
</svg>
That you can apply as background:
.white-grad {
background:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" ><defs><linearGradient id="Gradient" x1="0" x2="100" y1="0" y2="0" gradientUnits="userSpaceOnUse"><stop stop-color="%239c20aa" offset="0"/><stop stop-color="%23fb3570" offset="1"/></linearGradient></defs><rect x="5" y="5" width="100%" height="100%" style="height:calc(100% - 10px);width:calc(100% - 10px)" rx="20" ry="20" stroke-width="10" fill="transparent" stroke="url(%23Gradient)"/></svg>');
color: #313149;
padding:25px;
border-radius:15px;
display:inline-block;
margin: 75px 0;
}
body {
background:yellow;
}
<div class="white-grad"> Some text here</div>
<div class="white-grad"> text very loooooooooooong here</div>
And the same way as mask where you can get the gradient outside of the SVG:
.white-grad {
color: #313149;
padding: 25px;
border-radius: 15px;
display: inline-block;
margin: 75px 0;
background-size: 0 0;
position: relative;
z-index: 0;
}
.white-grad::before {
content: "";
position: absolute;
z-index: -1;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-image: inherit;
background-size: auto;
--mask: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" ><rect x="5" y="5" width="100%" height="100%" style="height:calc(100% - 10px);width:calc(100% - 10px)" rx="20" ry="20" stroke-width="10" fill="transparent" stroke="white"/></svg>');
-webkit-mask: var(--mask);
mask: var(--mask);
}
body {
background: yellow;
}
<div class="white-grad" style="background-image:linear-gradient(to right,blue,red)"> Some text here</div>
<div class="white-grad" style="background-image:linear-gradient(black,lightblue,green)"> text very loooooooooooong here</div>
<div class="white-grad" style="background-image:radial-gradient(blue,pink)"> text very<br> loooooooooooong here</div>
You can also use it as common element and consider position:absolute to place it around the text:
.white-grad {
color: #313149;
padding: 25px;
border-radius: 15px;
display: inline-block;
margin: 75px 0;
position:relative;
z-index:0;
}
.white-grad > svg {
position:absolute;
top:0;
left:0;
height:100%;
width:100%;
z-index:-1;
}
body {
background: yellow;
}
.hide {
height:0;
width:0;
}
<svg class="hide" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="Gradient" x1="0" x2="100" y1="0" y2="0" gradientUnits="userSpaceOnUse"><stop stop-color="#9c20aa" offset="0"/><stop stop-color="#fb3570" offset="1"/></linearGradient></defs><rect x="5" y="5" width="100%" height="100%" id="border" style="height:calc(100% - 10px);width:calc(100% - 10px)" rx="20" ry="20" stroke-width="10" fill="transparent" stroke="url(#Gradient)"/></svg>
<div class="white-grad">
<svg xmlns="http://www.w3.org/2000/svg">
<use href="#border" />
</svg>
Some text here</div>
<div class="white-grad">
<svg xmlns="http://www.w3.org/2000/svg">
<use href="#border" />
</svg>
text very loooooooooooong here</div>
CSS Mask method
Here is a different idea with CSS using mask where you will have transparency and it will also be responsive:
.white-grad {
color: #313149;
padding: 10px;
display: inline-block;
margin: 75px 0;
position: relative;
z-index: 0;
}
.white-grad:before {
content: "";
position: absolute;
z-index: -1;
inset: 0;
padding: 5px;
border-radius: 15px;
background: linear-gradient(to right, #9c20aa, #fb3570);
-webkit-mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
}
<div class="white-grad"> Some text here</div>
<div class="white-grad"> Some long long long text here</div>
<div class="white-grad"> Some long long <br>long text here</div>
With CSS variables, we can make it easy to adjust:
.white-grad {
--b:5px; /* border width*/
--r:15px; /* the radius */
color: #313149;
padding: calc(var(--b) + 5px);
display: inline-block;
margin: 75px 0;
position:relative;
z-index:0;
}
.white-grad:before {
content: "";
position: absolute;
z-index: -1;
inset: 0;
padding: var(--b);
border-radius: var(--r);
background: var(--c,linear-gradient(to right, #9c20aa, #fb3570));
-webkit-mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
}
body {
background:#f2f2f2;
}
<div class="white-grad"> Some text here</div>
<div class="white-grad" style="--r:20px;--b:10px;--c:linear-gradient(140deg,red,yellow,green)"> Some long long long text here</div>
<div class="white-grad" style="--r:30px;--b:8px;--c:linear-gradient(-40deg,black 50%,blue 0)"> Some long long <br>long text here</div>
<div class="white-grad" style="--r:40px;--b:20px;--c:conic-gradient(black,orange,purple)"> Some long long <br>long text here<br> more and more more and more</div>
Related question to get a different effect: How do you apply a gradient from outer to inner, only to borders, in CSS?
The above examples cover also the circle shape:
.white-grad {
--b:5px; /* border width*/
color: #313149;
display: inline-block;
margin: 10px;
width: 150px;
aspect-ratio: 1;
position: relative;
z-index: 0;
}
.white-grad:before {
content:"";
position:absolute;
z-index:-1;
inset: 0;
background: var(--c,linear-gradient(to right, #9c20aa, #fb3570));
padding: var(--b);
border-radius: 50%;
-webkit-mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
}
body {
background:#f2f2f2;
}
<div class="white-grad"></div>
<div class="white-grad" style="--b:10px;--c:linear-gradient(140deg,red,yellow,green)"></div>
<div class="white-grad" style="--b:8px;--c:linear-gradient(-40deg,black 50%,blue 0)"></div>
<div class="white-grad" style="--b:20px;--c:conic-gradient(black,orange,purple)"></div>
Related question in case you want to apply an animation to the border: Button with transparent background and rotating gradient border
Also different radius shapes:
.white-grad {
--b:5px; /* border width*/
color: #313149;
display: inline-block;
margin: 10px;
width: 150px;
aspect-ratio: 1;
position: relative;
z-index: 0;
}
.white-grad:before {
content: "";
position: absolute;
z-index: -1;
inset: 0;
background: var(--c,linear-gradient(to right, #9c20aa, #fb3570));
padding: var(--b);
border-radius: var(--r,50%);
-webkit-mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
}
body {
background:#f2f2f2;
}
<div class="white-grad" style="--r:50% 0 50% 50%;"></div>
<div class="white-grad" style="--b:10px;--r:50% 0;--c:linear-gradient(140deg,red,yellow,green)"></div>
<div class="white-grad" style="--b:8px;--r:50% 0 0;--c:linear-gradient(-40deg,black 50%,blue 0)"></div>
<div class="white-grad" style="--b:20px;--r:50% 50% 0 0;--c:conic-gradient(black,orange,purple)"></div>
and different border thickness:
.white-grad {
--b:5px; /* border width*/
color: #313149;
display: inline-block;
margin: 10px;
width: 150px;
aspect-ratio: 1;
position: relative;
z-index: 0;
}
.white-grad:before {
content: "";
position: absolute;
z-index: -1;
inset: 0;
background: var(--c,linear-gradient(#9c20aa, #fb3570));
padding: var(--b);
border-radius:var(--r,50%);
-webkit-mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
}
body {
background:#f2f2f2;
}
<div class="white-grad" style="--b:0 0 20px 20px;--r:50% 0 50% 50%;"></div>
<div class="white-grad" style="--b:10px 0 10px 0;--r:50% 0;--c:linear-gradient(140deg,red,yellow,green)"></div>
<div class="white-grad" style="--b:8px 0px 0px 8px;--r:50% 0 0;--c:linear-gradient(40deg,black 50%,blue 0)"></div>
<div class="white-grad" style="--b:20px 20px 0 20px;--r:50% 50% 0 0;--c:conic-gradient(pink,orange,red,pink)"></div>
You need to wrap the button in a div and set the border-radius on that parent div. In order to work, you will have to set overflow:hidden to that parent div as well. Like so:
.btn-wrap {
border-radius: 5px;
overflow: hidden;
margin: 20px;
width: 60px;
}
a.btn.white-grad {
background: #eee;
color: #313149 !important;
border: 20px solid #000;
border-image-source: linear-gradient(to right, #9c20aa, #fb3570);
border-image-slice: 20;
line-height: 2;
}
<div class="btn-wrap">
link
</div>

Resources