Recently I did some frontend work and wanted to spice up my buttons. I like rainbow colors and nice animations, so why not give buttons a moving rainbow border on hover? CSS is powerful but often has multiple ways that appear to accomplish the same thing, at least on the surface. The devil is in the details, so I tried different approaches to achieve this effect.
First, border
supports gradients, so maybe we can use this property?
Taken from this excellent blog post, it’s almost what I want. Unfortunately, though, it doesn’t support rounded edges. Also, it uses a custom property, and despite the post being three years old, custom properties are still not a thing in all browsers. There’s a workaround included, essentially generating the expected animation for the browser, but it’s a lot of boilerplate, and I don’t like bloating my file just for this.
Another option is using a pseudo-element behind the button and setting its background
. I played around with this, and
it seemed like the best option.
Unfortunately, I only found an example with a linear gradient while I wanted a conic one. Changing the gradient type is
easy, but then the animation was broken. Moving the background-position
works only for the scaled up linear gradient.
If I apply a rotate animation directly, we get this:
We need to clip away anything not part of the border.
I searched for clipping but only ended up
with clip-path
, svgs and the likes,
which could maybe work, but would be a hassle. masks
also didn’t look too promising.
Finally, overflow
saved me. I hadn’t seen the overflow: clip
property, and low and behold, it also comes
with overflow-clip-margin, giving us the space
for a beautiful border. This is perfect!
Now, I just had to center the pseudo-element, one of the most infamous tasks in CSS. Luckily inset: 0
combined
with margin: auto
gets us almost there, but for some reason, we also need to override left
with the explicit
indentation to offset the oversize width.
This is the final result, and although it feels a bit cursed, it works™:
Comments