<div class="content">
<div>
<h1>Gradient Borders</h1>
(With transparent background and border radius)
</div>
<hr>
<p>
There are many ways to create <b>gradient borders</b> for an element.
If you looked it up, you probably found Chris Coyier's great article about
<a href="https://css-tricks.com/gradient-borders-in-css/">Gradient Borders in CSS</a>,
where he describes how to create gradient borders with <code>pseudo-element</code>
and <code>border-image</code>.
</p>
<p>
The problem is that one method only supports opaque backgrounds,
and the other is incompatible with <code>border-radius</code>. So what do you
do when you need an element with gradient borders, and rounded corners, and a transparent
background?! You can use <code>background-image</code> for that.
</p>
<div class="btns">
<button class="btn">Lorem</button>
<button class="btn">ipsum</button>
<button class="btn">dolor</button>
<button class="btn">sit amet</button>
<button class="btn">consectetur</button>
<button class="btn">adipisicing</button>
<button class="btn">elit.</button>
<button class="btn">Ex vero</button>
<button class="btn">maiores</button>
<button class="btn">itaque id</button>
<button class="btn">aperiam</button>
<button class="btn">sequi</button>
</div>
<p>
It uses a very similar method as the one I've used in my
<a href="https://codepen.io/amit_sheen/pen/xxZeyjO">Dashed Border Generator</a>,
only with 8 background areas instead of 4, which allows for the rounded-corners effect.
</p>
</div>
<div class="generator">
<div class="sliders">
<h2>Create your own gradient border</h2>
<br>
<label>Border-width</label>
<input type="range" name="width" min="1" max="16" step="1" value="5" oninput="drawBtn();">
<label>Border-radius</label>
<input type="range" name="radius" min="1" max="32" step="1" value="20" oninput="drawBtn();">
</div>
<div class="resultBtn-wrepper">
<div class="resultBtn">
<input type="color" name="colorA" onchange="drawBtn();" value="#D50000">
<input type="color" name="colorB" onchange="drawBtn();" value="#304FFE">
<input type="color" name="colorC" onchange="drawBtn();" value="#00BFA5">
<input type="color" name="colorD" onchange="drawBtn();" value="#FFD600">
Result
</div>
</div>
</div>
<div class="output">
<h3>Output code:</h3>
<div class="output-code"></div>
</div>
<a href="https://twitter.com/amit_sheen" class="twitterLink" target="_blank">
<img src="https://assets.codepen.io/1948355/twitterLogo2.png" />
</a>
@import url('https://fonts.googleapis.com/css2?family=Open+Sans+Condensed:wght@300;700&display=swap');
@mixin bordient($radius, $width, $color1, $color2, $color3: $color2, $color4: $color1) {
background-image:
radial-gradient(circle at 100% 100%, transparent #{$radius - $width}, $color1 #{$radius - $width}, $color1 #{$radius}, transparent #{$radius}),
linear-gradient(to right, $color1, $color2),
radial-gradient(circle at 0% 100%, transparent #{$radius - $width}, $color2 #{$radius - $width}, $color2 #{$radius}, transparent #{$radius}),
linear-gradient(to bottom, $color2, $color3),
radial-gradient(circle at 0% 0%, transparent #{$radius - $width}, $color3 #{$radius - $width}, $color3 #{$radius}, transparent #{$radius}),
linear-gradient(to left, $color3, $color4),
radial-gradient(circle at 100% 0%, transparent #{$radius - $width}, $color4 #{$radius - $width}, $color4 #{$radius}, transparent #{$radius}),
linear-gradient(to top, $color4, $color1);
background-position:
top left,
top center,
top right,
center right,
bottom right,
bottom center,
bottom left,
center left;
background-size:
#{$radius} #{$radius},
calc(100% - (2 * #{$radius})) #{$width},
#{$radius} #{$radius},
#{$width} calc(100% - (2 * #{$radius}));
background-repeat: no-repeat;
}
*, *::before, *::after {
padding: 0;
margin: 0 auto;
box-sizing: border-box;
}
body {
font-family: 'Open Sans Condensed', sans-serif;
background-color: #333;
color: #fff;
min-height: 100vh;
background-image: repeating-linear-gradient(45deg, #222, #333 2px, #222 4px);
text-align: center;
}
a {
color: #0075ff;
}
h2, h3 {
text-decoration: underline;
text-decoration-color: #aaa;
}
hr {
width: 100%;
height: 8px;
background: none;
border: none;
@include bordient(0px, 2px, #D50000, #304FFE);
}
.content {
max-width: 720px;
padding: 4em 2em 2em;
background-color: #0004;
& p {
text-align: left;
font-size: 1.25em;
}
& > * + * {
margin-top: 2em;
}
}
.btns {
display: grid;
grid-gap: 1em 2em;
grid-template-columns: repeat(4, 1fr);
@media (max-width: 720px) {
grid-template-columns: repeat(3, 1fr);
}
@media (max-width: 480px) {
grid-template-columns: repeat(2, 1fr);
}
}
.btn {
font-size: 1em;
padding: 1em ;
width: 100%;
border: none;
background: none;
color: white;
font-weight: bold;
filter: drop-shadow(0px 0px 3px rgba(0,0,0,0.25));
transition: filter 0.2s;
&:hover {
filter: drop-shadow(3px 3px 3px rgba(0,0,0,0.5));
}
&:nth-child(1) {
@include bordient(12px, 8px, #D50000, #304FFE, #00BFA5, #FFD600);
}
&:nth-child(2) {
@include bordient(4px, 2px, #AA00FF, #0091EA, #64DD17, #FF6D00);
}
&:nth-child(3) {
@include bordient(4px, 3px, #C51162, #00C853);
}
&:nth-child(4) {
@include bordient(4px, 3px, #2962FF, #FFAB00, white);
}
&:nth-child(5) {
@include bordient(24px, 2px, white, red);
}
&:nth-child(6) {
@include bordient(12px, 4px, white, red, white, red);
}
&:nth-child(7) {
@include bordient(0px, 7px, white, white, lime, lime);
}
&:nth-child(8) {
@include bordient(16px, 4px, lime, white, lime, white);
}
&:nth-child(9) {
@include bordient(4px, 2px, aqua, gold, white, white);
}
&:nth-child(10) {
@include bordient(20px, 4px, aqua, gold);
}
&:nth-child(11) {
@include bordient(10px, 1px, tomato, white, tomato, maroon);
}
&:nth-child(12) {
@include bordient(1.5em, 1.5em, teal, maroon);
}
}
.generator {
max-width: calc(720px + 4em);
padding: 4em 2em 0;
display: grid;
grid-template-columns: auto min-content;
grid-gap: 2em;
align-items: center;
@media (max-width: 640px) {
grid-template-columns: 1fr;
grid-gap: 0em;
}
}
.sliders {
width: 100%;
text-align: left;
& input {
width: 100%;
margin-bottom: 2em;
}
}
.resultBtn {
&-wrepper {
text-align: center;
padding: 3em;
margin-bottom: 2em;
}
position: relative;
font-weight: bold;
font-size: 1.25em;
padding: 1em 3em;
border: none;
background: none;
color: #fff;
& input {
position: absolute;
width: 3em; height: 3em;
background: none;
border: none;
&:nth-child(1) { top: -3em; left: -3em; }
&:nth-child(2) { top: -3em; right: -3em; }
&:nth-child(3) { bottom: -3em; right: -3em; }
&:nth-child(4) { bottom: -3em; left: -3em; }
}
}
.output {
max-width: 720px;
text-align: left;
padding: 2em;
background-color: #0004;
&-code {
padding: 2em;
background-color: #fffa;
color: #333;
& span {
display: block;
padding-left: 4em;
text-indent: -2em;
margin: 0.5em auto;
}
}
}
.twitterLink {
position: fixed;
bottom: 0.5em; right: 0.5em;
& img {
width: 2em;
filter: grayscale(100%);
transition: filter 0.25s;
&:hover {
filter: grayscale(0%);
}
}
}
View Compiled
const resultBtn = document.querySelector('.resultBtn');
const output = document.querySelector('.output-code');
resultBtn.style.backgroundPosition = `top left,top center,top right,center right, bottom right,bottom center,bottom left,center left`;
resultBtn.style.backgroundRepeat = "no-repeat";
drawBtn();
function drawBtn() {
const width = Number(document.querySelector('[name="width"]').value);
const radius = Number(document.querySelector('[name="radius"]').value);
const color = [
document.querySelector('[name="colorA"]').value,
document.querySelector('[name="colorB"]').value,
document.querySelector('[name="colorC"]').value,
document.querySelector('[name="colorD"]').value
]
resultBtn.style.backgroundImage = `
radial-gradient(circle at 100% 100%, transparent ${radius - width}px, ${color[0]} ${radius - width}px, ${color[0]} ${radius}px, transparent ${radius}px),
linear-gradient(to right, ${color[0]}, ${color[1]}),
radial-gradient(circle at 0% 100%, transparent ${radius - width}px, ${color[1]} ${radius - width}px, ${color[1]} ${radius}px, transparent ${radius}px),
linear-gradient(to bottom, ${color[1]}, ${color[2]}),
radial-gradient(circle at 0% 0%, transparent ${radius - width}px, ${color[2]} ${radius - width}px, ${color[2]} ${radius}px, transparent ${radius}px),
linear-gradient(to left, ${color[2]}, ${color[3]}),
radial-gradient(circle at 100% 0%, transparent ${radius - width}px, ${color[3]} ${radius - width}px, ${color[3]} ${radius}px, transparent ${radius}px),
linear-gradient(to top, ${color[3]}, ${color[0]})
`;
resultBtn.style.backgroundSize = `
${radius}px ${radius}px,
calc(100% - ${2 * radius}px) ${width}px,
${radius}px ${radius}px,
${width}px calc(100% - ${2 * radius}px)
`;
output.innerHTML = `
<code>
.button-with-gradient-border {
<span>
<b>background-image</b>:
radial-gradient(circle at 100% 100%, transparent ${radius - width}px, ${color[0]} ${radius - width}px, ${color[0]} ${radius}px, transparent ${radius}px),
linear-gradient(to right, ${color[0]}, ${color[1]}),
radial-gradient(circle at 0% 100%, transparent ${radius - width}px, ${color[1]} ${radius - width}px, ${color[1]} ${radius}px, transparent ${radius}px),
linear-gradient(to bottom, ${color[1]}, ${color[2]}),
radial-gradient(circle at 0% 0%, transparent ${radius - width}px, ${color[2]} ${radius - width}px, ${color[2]} ${radius}px, transparent ${radius}px),
linear-gradient(to left, ${color[2]}, ${color[3]}),
radial-gradient(circle at 100% 0%, transparent ${radius - width}px, ${color[3]} ${radius - width}px, ${color[3]} ${radius}px, transparent ${radius}px),
linear-gradient(to top, ${color[3]}, ${color[0]});
</span>
<span>
<b>background-size</b>:
${radius}px ${radius}px,
calc(100% - ${2 * radius}px) ${width}px,
${radius}px ${radius}px,
${width}px calc(100% - ${2 * radius}px);
</span>
<span>
<b>background-position</b>:
top left,top center,top right,center right, bottom right,bottom center,bottom left,center left;
</span>
<span>
<b>background-repeat</b>:
no-repeat;
</span>
}
</code>
`;
}
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.