Create an Animated Shine Border Button With CSS Masks

Last week, I stumbled upon this neat little effect on the Saner.io website, where the call to action button has a border shine flowing around the button, making the button quite eye-catching.

Create an Animated Shiny Border Button With CSS Masks

I haven’t really seen anything like this before, and thought JavaScript must have been used behind the scenes, but after digging into the inspector panel, I discovered that it was created with pure CSS – more specifically with CSS masks and composite masking.

Let’s go through my breakdown of creating this animated shine border button effect. The demo can be found here!

1. Initial Setup for Our Animated Shine Border Button

Below, I’ll create the structure of the HTML and CSS files, and just add in some ‘call to action’ content, along with the link / button.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" type="text/css" href="style.css">
    <title>Animated Border Button</title>

</head>
<body>

    <h2>Leave the Rest, Get the Best</h2>
    <p>Don't just accept mediocrity, choose better!</p>
        
    <a href="#" class="feh-shiny-button">
        Contact Us Today!
    </a>
            
</body>
</html>

The initial CSS just resets the body's margins / paddings, adds some basic styling, formats the 'CTA' heading/paragraph and centers everything, so we are left with the below:

Here, we are just styling the link up to make it look like a button by adding padding, colours, increasing the font size. But also notice that we add position: relative; This is added because the mask inside will use absolute positioning.

.feh-shiny-button {
    position: relative;
    padding: 20px 32px;
    border-radius: 12px;
    color: #fff;
    font-size: 18px;
    font-weight: 500;
    text-decoration: none;
    background: #1F1F1F;
    transition: all 0.3s ease;
}
    .feh-shiny-button:hover {
        background: #333;
    }

Everything should be pretty easy to follow here, we've just added some styles to make the link look like a button, but also a transition property that will add a smooth background colour change when we hover over the button.

So, we are left with this 😍

3. Creating an Overlay Border with CSS Masks

Now, we are going to add in some extra HTML into our link mark-up, that will contain the mask and shine effect.

<a href="#" class="feh-shiny-button">
    <div class="feh-border-mask">
        <div class="feh-border-glow"></div>
    </div>
    Contact Us Today!
</a>

So, inside our link .feh-shiny-button code, we have added two divs with the classes:

  • .feh-border-mask
  • .feh-border-glow

Now, we need to add in the CSS styles for the first new div .feh-border-mask.

.feh-border-mask {
    position: absolute;
    top: 0;
    left: 0;
    border-radius: 12px;
    width: 100%;
    height: 100%;
    padding: 1px;
    mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0) border-box;
    mask-composite: exclude;
}

What the above CSS does is create a hollow border effect using CSS masking.

It positions an absolutely positioned div (.feh-border-mask) over the entire link/button, then uses the mask property with mask-composite: exclude to 'cut out' the inner content area, leaving only a 1px border visible around the edges.

You won't be able to see anything change with this code, we need to add in the 'shine' effect next, but below is my attempt at trying to show this border mask, displayed as a one pixel red border. Everything inside this 1px area will contain the shine effect.

4. Adding the Glow/Shine Effect

Now, it's time to add in the border glow effect for the .feh-border-glow div, which is essentially a background conic-gradient with four colour stops:

conic-gradient(from 0deg, 
    transparent 0%, 
    #fff 10%, 
    #000 15%, 
    transparent 20%
);

...and the full css block:

.feh-border-glow {
    background: conic-gradient(from 0deg, transparent 0%, #fff 10%, #000, transparent 20%);
    position: absolute;
    top: 50%;
    left: 50%;
    width: 500px;
    height: 500px;
    transform: translate(-50%, -50%);
    transform-origin: 0 0;
}

So, what have we done here?

  • We have created a conic gradient that transitions from transparent, to white, to black, and finally back to transparent. We have added transparency to the first and last colour stops to make make the glow 'feathered'.
  • We've made the div 500px x 500px, to make sure it covers the entire button.
  • And finally, we have centered this .feh-border-glow div and made it so that this div will rotate from 0 0, which is from the top left corner.

So, we get the following:

We can't really see much though, eh? If I comment out the mask property...

.feh-border-mask {
    ....
    /* mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0) border-box; */
}

...we can see the gradient in all of its glory:

Let's leave the mask property commented out for the moment and move on to the final part in this tutorial – rotating the glow effect!

5. Rotating the glowing border

To make this border effect really work its magic, we need to rotate it with a simple @keyframes animation. I will call this keyframe animation rotateShine.

@keyframes rotateShine {
    0% { 
        transform: rotate(0deg) translate(-50%, -50%);
    }
    100% { 
        transform: rotate(360deg) translate(-50%, -50%);
    }
} 

and then add an animation property inside of the .feh-border-mask ruleset:

.feh-border-glow {
    ...
    animation: rotateShine 3s linear infinite;
}

You can see above, that my rotateShine keyframe name is there, the duration of the animation will be three seconds, it will animate at a constant speed (linear) and it will run indefinitely.

Now, with the animation running, we can get a clear picture of how this effect works:

And with the mask uncommented, we get the final effect 😍

6. Conclusion on Creating an Animated Shine Border Button With CSS Masks

And there you have it! We've successfully recreated that eye-catching animated shine border effect using nothing but pure CSS. What initially appeared to require JavaScript turned out to be achievable through the clever combination of CSS masks, conic gradients, and keyframe animations.

If this tutorial has helped you, I wouldn't say no to a coffee as a tip ☕️

Buy Me a Coffee at ko-fi.com

3 thoughts on "Create an Animated Shine Border Button With CSS Masks"

  1. Why is the whole codebase not on github?! This post is so annoying.

    1. Thoughts and prayers to you in this difficult time 🙏🏻

  2. Any idea how it could be done with transparent button fill?

Leave a Reply

Your email address will not be published. Required fields are marked *