skip to Main Content

I have unsuccessfully been trying to animate a linear gradient border on a div. I took inspiration from
this image. I want the border to be transparent between the two gradients, like in the picture. But I also want the gradient to look like it is moving in a circle around the circle div.

I tried making the circle rotate in an animation, which works but I cannot add a gradient to a border-color property so instead I used an ::after property to add a circle behind the main div so that it looks like a circle. All of this works with a on the background but the main problem from here is that I cannot get the gaps between 2 different gradient borders on opposite sides of the circle.

scss:

#home-page {
    i {
        position: absolute;
        color: $medium-red;
        top: 50%;
        left: 50%;
        font-size: 400px;
        // border-width: 2px;
        // border-style: solid;
        animation: spin 4s linear infinite;
        // border-color: transparent $beige;
        border-radius: 50%;

        &::after {
            content: "";
            background: linear-gradient(60deg, $beige, $light-red);
            position: absolute;
            top: -3px;
            left: -3px;
            right: -3px;
            bottom: -3px;
            border-radius: 50%;
            z-index: -1;
        }
    }
}

@keyframes spin {
    0% {
        transform: translate(-50%, -50%);
    }

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

html:

<div id="homepage">
    <i>(font awesome icon of a circle)</i>
</div>

2

Answers


  1. HTML

    <div id="homepage">
        <div class="circle-gradient">
        </div>
    </div>
    

    CSS:

    .circle-gradient {
        color: $medium-red;
        animation: spin 4s linear infinite;
        border-radius: 50%;
        position: relative;
        height: 300px;
        width: 300px;
        background: linear-gradient(60deg, $beige, $light-red);
        border-radius: 50%;
        z-index: -1;
        position: relative;
        &:after{
          content: '';
          position: absolute;
          width: 100%;
          height: 100%;
          background-color: white;
          border-radius: 50%;
          z-index: 999;
          border-inline: 5px solid rgba(0,0,0,0.02);
        }
    }
    
    @keyframes spin {
      0% {
        transform: translate(1%, 1%);
      }
    
      100% {
        transform: translate(1%, 1%) rotate(360deg);
      }
    }
    

    test how it works HERE

    Login or Signup to reply.
  2. You could use SVG for the gradient arcs like:

    // https://stackoverflow.com/a/18473154/383904
    const polarToCartesian = (centerX, centerY, radius, angleInDegrees) => {
      const angleInRadians = (angleInDegrees - 90) * Math.PI / 180.0;
      return {
        x: centerX + (radius * Math.cos(angleInRadians)),
        y: centerY + (radius * Math.sin(angleInRadians))
      };
    };
    
    const describeArc = (x, y, radius, startAngle, endAngle) => {
      const start = polarToCartesian(x, y, radius, endAngle);
      const end = polarToCartesian(x, y, radius, startAngle);
      const largeArcFlag = endAngle - startAngle <= 180 ? "0" : "1";
      const d = [
        "M", start.x, start.y,
        "A", radius, radius, 0, largeArcFlag, 0, end.x, end.y
      ].join(" ");
      return d;
    };
    
    document.querySelector("#arc1 path").setAttribute("d", describeArc(0.5, 0.5, 0.48, -30, 30));
    document.querySelector("#arc2 path").setAttribute("d", describeArc(0.5, 0.5, 0.48, 180 - 15, 180 + 15));
    * { margin: 0; }
    
    body {
      background: #1a0a0a;
    }
    
    .circle {
      position: relative;
      width: 8rem;
      aspect-ratio: 1;
      border-radius: 50%;
      background: url("https://i.stack.imgur.com/p2rd3.png") no-repeat center / 60%;
    }
    
    .circle svg {
      position: absolute;
      animation: arcRotation 2s linear infinite ;
    }
    
    @keyframes arcRotation {
      100% { rotate: 360deg; }
    }
    <svg height=0 width=0>
      <defs>
        <linearGradient id="gradient" gradientUnits="userSpaceOnUse" x1="1" y1="1" x2="0" y2="1">
          <stop offset=".42" stop-color="#fff" />
          <stop offset=".58" stop-color="#f00" />
        </linearGradient>
      </defs>
    </svg>
    
    <div class="circle">
      <svg id="arc1" viewBox="0 0 1 1">
        <path stroke="url(#gradient)" stroke-width="0.01" fill="none" />
      </svg>
      <svg id="arc2" viewBox="0 0 1 1">
        <path stroke="url(#gradient)" stroke-width="0.01" fill="none" />
      </svg>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search