Search code examples
csssvgcss-shapessvg-animate

SVG progress bar


I have a requirement where I need to load js files dynamically and show the progress of loading files through a SVG icon. The SVG icon will act as progress bar where it fills with a color from bottom to top, linearly.

Here is the codepen

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="79.36px" height="93.844px" viewBox="0 0 79.36 93.844">

  <path fill="transparent" stroke="black" d="M50,2C30-4,8,7,2,28c-6,20,5,42,26,48h0l-4,15l33-18c0-0,0-0,1-0l0-0l-0-0c8-4,15-12,17-22C83,30,71,8,50,2z" />
</svg>

I am planning to make this icon independent such that I will only pass the percentage value dynamically.

I somehow able to get the animation done but unable to keep the border or outline of the svg. Here is the code.

#progressMove {
  transition: .3s y;
}
#progressMove:hover {
  y: 60%;
}
<svg id="kenseoProgress" width="79.36px" height="93.844px" viewBox="0 0 79.36 93.844">
  <defs>
    <mask id="bubbleKenseo">
      <path fill="red" stroke="black" d="M50,2C30-4,8,7,2,28c-6,20,5,42,26,48h0l-4,15l33-18c0-0,0-0,1-0l0-0l-0-0c8-4,15-12,17-22C83,30,71,8,50,2z" />
    </mask>
  </defs>
  <g x="0" y="0" width="79.36px" height="93.844px" mask="url(#bubbleKenseo)" height="100">
    <rect id="progressMove" x="0" y="0%" width="100%" height="100%" fill="blue" stroke="black" />
  </g>
</svg>

So, the problems I have are:

  • Unable to maintain the border to the SVG
  • Whatever the color I add is having some kind of opacity which I am unable to remove.
  • Edit: Browser compatibility: IE11+, chrome, safari and firefox

PS: I don't want to use SMIL animations.


Solution

  • First off, you want to use clip-path, or set the mask fill to white for 100% opacity: mask is used as a greyscale alpha channel and the red fill color causes the opacity change.

    As for the stroke, you want to add it as a separate element that is not affected by the clipping. (You can probably re-use the path with defs and use, I just copy-pasted it here)

    #progressMove {
      transition: .3s y;
    }
    #progressMove:hover {
      y: 60%;
    }
    <svg id="kenseoProgress" width="79.36px" height="93.844px" viewBox="0 0 79.36 93.844">
      <defs>
        <clipPath id="bubbleKenseo">
          <path d="M50,2C30-4,8,7,2,28c-6,20,5,42,26,48h0l-4,15l33-18c0-0,0-0,1-0l0-0l-0-0c8-4,15-12,17-22C83,30,71,8,50,2z" />
        </clipPath>
      </defs>
      <path stroke="black" stroke-width="1" fill="transparent" d="M50,2C30-4,8,7,2,28c-6,20,5,42,26,48h0l-4,15l33-18c0-0,0-0,1-0l0-0l-0-0c8-4,15-12,17-22C83,30,71,8,50,2z" />
      <g x="0" y="0" width="79.36px" height="93.844px" clip-path="url(#bubbleKenseo)" height="100">
        <rect id="progressMove" x="0" y="0%" width="100%" height="100%" fill="blue" stroke="black" />
      </g>
    </svg>