DEV Community

Cover image for Creating an animated gradient border with CSS
Ibelick
Ibelick

Posted on • Edited on • Originally published at julienthibeaut.xyz

Creating an animated gradient border with CSS

Note: This article was originally published on my personal blog. For more updates, follow me on Twitter @ibelick.


In this article, I'll share methods for creating an animated gradient border with CSS. You can easily customize the border color, animation speed, border size, and border radius with theses techniques.

gif animated gradient

Code

Property and background clip

We use the @property rule, it comes with limited supports you can check the brower support here caniuse.
For a more supported method, you can go to the end of the article.

<div class="box">{children}</div>
Enter fullscreen mode Exit fullscreen mode
.box {
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 12px;
  height: 400px;
  width: 400px;
  border: 3px solid #0000;
  border-radius: 12px;
  background: linear-gradient(#131219, #131219) padding-box, linear-gradient(
        var(--angle),
        #070707,
        #687aff
      ) border-box;
  animation: 8s rotate linear infinite;
}

@keyframes rotate {
  to {
    --angle: 360deg;
  }
}

@property --angle {
  syntax: "<angle>";
  initial-value: 0deg;
  inherits: false;
}
Enter fullscreen mode Exit fullscreen mode

To achieve our desired effect, we'll use the following CSS properties:

  • border: This property creates a 1px wide, solid, transparent border around the box.
  • border-radius: This property gives the box rounded corners with a 12px radius.
  • background: This property creates a two-layered background using two linear gradients. The first gradient is a solid color (#000) that fills the box's padding area. The second gradient creates the shiny effect and is animated using the custom property --angle. The gradient is applied to the box's border area. We use the backgroud-clip property to specify that the background should be clipped to the padding box.
  • animation: This property applies the "rotate" animation to the box. It has an 8-second duration, uses linear easing, and repeats infinitely.
  • @keyframes rotate: This keyframe animation block specifies the end state of the "rotate" animation, where the custom property --angle is set to 360deg.
  • @property --angle: This part of the code defines the custom property --angle using the CSS Houdini @property rule. It specifies the expected syntax (angle), the initial value (0deg), and that the property does not inherit from parent elements.

Tailwind CSS

If you prefer using Tailwind CSS, here's the equivalent code written with React and TypeScript:

export const AnimatedGradientBorderTW: React.FC<{
  children: React.ReactNode;
}> = ({ children }) => {
  const boxRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    const boxElement = boxRef.current;

    if (!boxElement) {
      return;
    }

    const updateAnimation = () => {
      const angle =
        (parseFloat(boxElement.style.getPropertyValue("--angle")) + 0.5) % 360;
      boxElement.style.setProperty("--angle", `${angle}deg`);
      requestAnimationFrame(updateAnimation);
    };

    requestAnimationFrame(updateAnimation);
  }, []);

  return (
    <div
      ref={boxRef}
      style={
        {
          "--angle": "0deg",
          "--border-color": "linear-gradient(var(--angle), #070707, #687aff)",
          "--bg-color": "linear-gradient(#131219, #131219)",
        } as CSSProperties
      }
      className="flex h-[400px] w-[400px] items-center justify-center rounded-lg border-2 border-[#0000] p-3 [background:padding-box_var(--bg-color),border-box_var(--border-color)]"
    >
      {children}
    </div>
  );
};
Enter fullscreen mode Exit fullscreen mode

In this implementation, we handle the animation using JavaScript. We utilize the requestAnimationFrame function to update the custom property --angle every 16ms (60fps).

CSS Pseudo-Elements

If you want to support more browsers, you can use the following method instead:

.box__bg {
  position: relative;
  z-index: 0;
  height: 400px;
  width: 400px;
  border-radius: 12px;
  overflow: hidden;
  padding: 12px;
}

.box__bg::before {
  content: "";
  position: absolute;
  z-index: -2;
  left: -50%;
  top: -50%;
  width: 200%;
  height: 200%;
  background-color: #000;
  background-repeat: no-repeat;
  background-size: 100%100%, 50%50%;
  background-position: 0 0, 100% 0, 100% 100%, 0 100%;
  background-image: linear-gradient(#070707, #687aff);
  animation: bgRotate 4s linear infinite;
}

.box__bg::after {
  content: "";
  position: absolute;
  z-index: -1;
  left: 1px;
  top: 1px;
  width: calc(100% - 2px);
  height: calc(100% - 2px);
  background: linear-gradient(#06021d, #06021d);
  border-radius: 12px;
}

@keyframes bgRotate {
  100% {
    transform: rotate(1turn);
  }
}
Enter fullscreen mode Exit fullscreen mode

This technique uses ::before and ::after pseudo-elements to create the border and background layers, respectively. The ::before pseudo-element contains the animated gradient, rotating infinitely over 4 seconds using the bgRotate keyframes. The ::after pseudo-element is positioned above the gradient layer and sets the background color. The div itself has a fixed size, border-radius, and padding, with its overflow hidden to ensure the animated border is contained within the specified area.

More

Here we explore a few different ways to animate borders in CSS.
I recommend this article if you want to dive deeper into the topic.
Feel free to experiment and adapt the techniques discussed in this tutorial to fit your specific design needs and preferences. Let's connect on Twitter @ibelick ✌️

Top comments (0)