Home
    About
    Thoughts
    Playground
    Projects
Loading...
Design engineering

CSS Animated Borders… urgh

First published: 03 May 2025

My kingdom for CSS borders that can actually be animated… There has to be a better way?

I was working on setting up a new animation for the way the DuckDuckGo AI-assisted answers appear. Based on a recent NNg article about AI discoverability and how poor it is in many apps (particularly Amazon's in this case), I recognised that there was an opportunity to help signpost to people that this content had been generated by AI without having to spell it out too much.

In order to do this, there were many, many, many... many... explorations around states we could do. From multiple typing animations, to blurred reveals, to a scanner-style wipe, to a glowing border. That border was where we decided we had something that began to feel right.

Glowing borders aren't new, I mean, Apple Intelligence uses them everywhere, and plenty of other websites and products do various border animations. I explored a multitude of different approaches before landing on a simple outline stroke with transparent edges that would travel around the outside of the module as the content was either generating, or had been finally generated.

CleanShot 2025-05-03 at 17.11.59.gif

Above you can see the final version we landed on for both a cached answer, and a non-cached answer. Notice that the border animation is timed differently depending on each case.

Now, this seems simple and fun. Hell, in Figma you can easily create the look of this in a static mock no problem. But when it comes to implementation, it gets fun and hairy.

The way I chose to implement this was simple in the end, but took a hot minute to get there.

First, create a background wrapper element

Loading code...

Then, before that wrapper (so behind it) we apply a conic gradient that we can animate

Loading code...

Then above the background wrapper, we need a content layer to cover over the conic gradient, and slightly inset it to leave a gap for the "border" to show through

Loading code...

Then, we animate the glow by rotating the conic gradient

Loading code...

This... this is how complicated it was to achieve what I wanted. Why can't I just directly animate a border with some simple properties? The below is just a rough example, but yeah, why not?

Loading code...
Last updated: 06 May 2025 (3 months ago)
Loading...
Loading...

More to explore in design engineering
    Loading...
    Loading...
    Loading...
    Loading...
.backgroundWrapper {
    position: absolute;
    inset: 0;
    overflow: hidden;
    border-radius: 12px;
}
.backgroundWrapper::before {
    content: '';
    position: absolute;
    inset: -20px;
    background: conic-gradient(
        rgba(37, 106, 248, 0.8),
        rgba(37, 106, 248, 0.6),
        rgba(37, 106, 248, 0.4),
        rgba(37, 106, 248, 0.1),
        rgba(37, 106, 248, 0.4),
        rgba(37, 106, 248, 0.6),
        rgba(37, 106, 248, 0.8)
    );
    filter: blur(24px);
    opacity: 0;

    @media (prefers-color-scheme: dark) {
        background: conic-gradient(
            rgba(114, 149, 246, 0.8),
            rgba(114, 149, 246, 0.6),
            rgba(114, 149, 246, 0.4),
            rgba(114, 149, 246, 0.1),
            rgba(114, 149, 246, 0.4),
            rgba(114, 149, 246, 0.6),
            rgba(114, 149, 246, 0.8)
        );
    }
}
.backgroundWrapper::after {
    content: '';
    position: absolute;
    inset: 1.5px;
    background: white;
    border-radius: 10.5px; // to offset the inset
}


/* Content layer */
.content {
    position: relative;
    z-index: 1;
}
@keyframes rotate-glow {
    0% {
        transform: rotate(0deg);
        opacity: 0;
    }
    15% {
        opacity: 1;
    }
    85% {
        opacity: 1;
    }
    100% {
        transform: rotate(180deg);
        opacity: 0;
    }
}

@keyframes rotate-glow-continuous {
    0% {
        transform: rotate(0deg);
        opacity: 0;
    }
    15% {
        opacity: 1;
    }
    85% {
        opacity: 1;
    }
    100% {
        transform: rotate(360deg);
        opacity: 0;
    }
}

@keyframes completion-glow {
    0% {
        opacity: 0;
        filter: blur(24px);
    }
    50% {
        opacity: 1;
        filter: blur(24px);
    }
    100% {
        opacity: 0;
        filter: blur(24px);
    }
}

.animateBorder .backgroundWrapper::before {
    animation: rotate-glow 1s linear forwards;
}

.animateBorderContinuous .backgroundWrapper::before {
    animation: rotate-glow-continuous 2.5s linear infinite;
}

.animateCompletion .backgroundWrapper::before {
    animation: completion-glow 2s ease-out forwards;
    animation-delay: 200ms;
    background: blue;
}
.borderAnimation {
	border: 
		1px,
		linear-gradient(
        	rgba(37, 106, 248, 0.1),
        	rgba(37, 106, 248, 1),
        	rgba(37, 106, 248, 0.1)
    	);
	animation: rotate-glow 1s linear forwards;
};
Subscribe

Get an email whenever I publish a new thought.

Or you can subscribe via RSS
design engineering04 Aug 2025
On Vibe Coding

Keep AI coding assistants on a tight leash - they're smart but lack taste for good code.

design engineering24 Jul 2025
The Roadmap to Design Engineer

Unlock your design engineering potential with AI tools like Cursor and MCP—where creativity meets technical precision for revolutionary innovation.

design engineering08 Jun 2025
Full Circle

Bill Atkinson's legacy reveals technology's true purpose: human experience. Now, AI is reuniting design and development once again.

design engineering05 Jun 2025
The Messy Middle

Design engineers navigate the 'messy middle' of product development, turning creative vision into reality through technical skill and thoughtful collaboration.