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