I made a fancy custom checkbox that animates a gradient in/out when (un)checked. How can I make the checkbox border a gradient, as well? The border gradient should match the fill gradient just like the solid-colored fancy checkboxes.
I tried both the wrapping and pseudo-element methods described here: https://css-tricks.com/gradient-borders-in-css. However these methods:
/*Based on: https://moderncss.dev/pure-css-custom-checkbox-style/ */
input[type='checkbox'] {
appearance: none;
background-color: #fff !important;
display: inline-grid;
place-content: center;
color: purple;
border-color: purple;
}
input[type='checkbox']::before {
content: '';
width: inherit;
height: inherit;
border-radius: inherit;
transform: scale(0);
transition: 500ms transform ease-in-out;
background: purple;
}
input[type='checkbox']:checked::before {
transform: scale(1);
transition: 500ms transform ease-in-out;
background: purple;
}
input[type='checkbox'].gradient-bg::before {
background: linear-gradient(45deg, blue 20%, red 80%);
}
<div class=container>
<input type="checkbox" class="gradient-bg" checked />
<input type="checkbox" class="gradient-bg" />
<input type="checkbox" checked />
<input type="checkbox" />
</div>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css">
Adding the following code achieves the gradient border with a combination of transparent border, background-image
, and background-clip
:
input[type='checkbox'].gradient-bg {
border: calc(var(--pico-border-radius) / 2) solid transparent;
border-radius: var(--pico-border-radius);
background-image: linear-gradient(white, white), linear-gradient(45deg, blue 20%, red 80%);
background-origin: padding-box, border-box;
background-clip: padding-box, border-box;
}
I originally didn't even try the border-image
method because the article said "it’s just incompatible with border-radius, unfortunately." However, MDN docs for border-image
has an example for rounded borders:
border-radius has no effect on the border image. This is because border-image-outset is able to place the image outside the border box, so it doesn't make sense for the border image to be clipped by the border area. To create rounded borders when using a border image, you should create the image itself with rounded corners, or, in the case of a gradient, draw it as the background instead...
This YouTube video explains this double background-image technique in more detail. This technique doesn't work if the content inside the gradient border needs to be semi-transparent. So the video goes on to extend the method with masks so it works with transparent backgrounds.
/*Based on: https://moderncss.dev/pure-css-custom-checkbox-style/ */
input[type='checkbox'] {
appearance: none;
background-color: #fff !important;
display: inline-grid;
place-content: center;
color: purple;
border-color: purple;
}
input[type='checkbox']::before {
content: '';
width: inherit;
height: inherit;
border-radius: inherit;
transform: scale(0);
transition: 500ms transform ease-in-out;
background: purple;
}
input[type='checkbox']:checked::before {
transform: scale(1);
transition: 500ms transform ease-in-out;
background: purple;
}
input[type='checkbox'].gradient-bg::before {
background: linear-gradient(45deg, blue 20%, red 80%);
}
input[type='checkbox'].gradient-bg {
border: calc(var(--pico-border-radius) / 2) solid transparent;
border-radius: var(--pico-border-radius);
background-image: linear-gradient(white, white), linear-gradient(45deg, blue 20%, red 80%);
background-origin: padding-box, border-box;
background-clip: padding-box, border-box;
}
<div class=container>
<input type="checkbox" class="gradient-bg" checked />
<input type="checkbox" class="gradient-bg" />
<input type="checkbox" checked />
<input type="checkbox" />
</div>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css">