CSS Progress Circle

152
January 26, 2022, at 9:00 PM

I have searched this website to find progress bars, but the ones I have been able to found show animated circles that go to the full 100%.

I would like it to stop at certain percentages like in the screenshot below. Is there any way I can do that using only CSS?

Answer 1

I created a fiddle using only CSS.

.wrapper { 
  width: 100px; /* Set the size of the progress bar */ 
  height: 100px; 
  position: absolute; /* Enable clipping */ 
  clip: rect(0px, 100px, 100px, 50px); /* Hide half of the progress bar */ 
} 
/* Set the sizes of the elements that make up the progress bar */ 
.circle { 
  width: 80px; 
  height: 80px; 
  border: 10px solid green; 
  border-radius: 50px; 
  position: absolute; 
  clip: rect(0px, 50px, 100px, 0px); 
} 
/* Using the data attributes for the animation selectors. */ 
/* Base settings for all animated elements */ 
div[data-anim~=base] { 
  -webkit-animation-iteration-count: 1;  /* Only run once */ 
  -webkit-animation-fill-mode: forwards; /* Hold the last keyframe */ 
  -webkit-animation-timing-function:linear; /* Linear animation */ 
} 
 
.wrapper[data-anim~=wrapper] { 
  -webkit-animation-duration: 0.01s; /* Complete keyframes asap */ 
  -webkit-animation-delay: 3s; /* Wait half of the animation */ 
  -webkit-animation-name: close-wrapper; /* Keyframes name */ 
} 
 
.circle[data-anim~=left] { 
  -webkit-animation-duration: 6s; /* Full animation time */ 
  -webkit-animation-name: left-spin; 
} 
 
.circle[data-anim~=right] { 
  -webkit-animation-duration: 3s; /* Half animation time */ 
  -webkit-animation-name: right-spin; 
} 
/* Rotate the right side of the progress bar from 0 to 180 degrees */ 
@-webkit-keyframes right-spin { 
  from { 
    -webkit-transform: rotate(0deg); 
  } 
  to { 
    -webkit-transform: rotate(180deg); 
  } 
} 
/* Rotate the left side of the progress bar from 0 to 360 degrees */ 
@-webkit-keyframes left-spin { 
  from { 
    -webkit-transform: rotate(0deg); 
  } 
  to { 
    -webkit-transform: rotate(360deg); 
  } 
} 
/* Set the wrapper clip to auto, effectively removing the clip */ 
@-webkit-keyframes close-wrapper { 
  to { 
    clip: rect(auto, auto, auto, auto); 
  } 
}
<div class="wrapper" data-anim="base wrapper"> 
  <div class="circle" data-anim="base left"></div> 
  <div class="circle" data-anim="base right"></div> 
</div>

Also check this fiddle here (CSS only)

@import url(http://fonts.googleapis.com/css?family=Josefin+Sans:100,300,400); 
     
.arc1 { 
    width: 160px; 
    height: 160px; 
    background: #00a0db; 
    -webkit-transform-origin: -31% 61%; 
    margin-left: -30px; 
    margin-top: 20px; 
    -webkit-transform: translate(-54px,50px); 
    -moz-transform: translate(-54px,50px); 
    -o-transform: translate(-54px,50px); 
} 
.arc2 { 
    width: 160px; 
    height: 160px; 
    background: #00a0db; 
    -webkit-transform: skew(45deg,0deg); 
    -moz-transform: skew(45deg,0deg); 
    -o-transform: skew(45deg,0deg); 
    margin-left: -180px; 
    margin-top: -90px; 
    position: absolute; 
    -webkit-transition: all .5s linear; 
    -moz-transition: all .5s linear; 
    -o-transition: all .5s linear; 
} 
 
.arc-container:hover .arc2 { 
    margin-left: -50px; 
    -webkit-transform: skew(-20deg,0deg); 
    -moz-transform: skew(-20deg,0deg); 
    -o-transform: skew(-20deg,0deg); 
} 
 
.arc-wrapper { 
    width: 150px; 
    height: 150px; 
    border-radius:150px; 
    background: #424242; 
    overflow:hidden; 
    left: 50px; 
    top: 50px; 
    position: absolute; 
} 
.arc-hider { 
    width: 150px; 
    height: 150px; 
    border-radius: 150px; 
    border: 50px solid #e9e9e9; 
    position:absolute; 
    z-index:5; 
    box-shadow:inset 0px 0px 20px rgba(0,0,0,0.7); 
} 
 
.arc-inset  { 
    font-family: "Josefin Sans"; 
    font-weight: 100; 
    position: absolute; 
    font-size: 413px; 
    margin-top: -64px; 
    z-index: 5; 
    left: 30px; 
    line-height: 327px; 
    height: 280px; 
    -webkit-mask-image: -webkit-linear-gradient(top, rgba(0,0,0,1), rgba(0,0,0,0.2)); 
} 
.arc-lowerInset { 
    font-family: "Josefin Sans"; 
    font-weight: 100; 
    position: absolute; 
    font-size: 413px; 
    margin-top: -64px; 
    z-index: 5; 
    left: 30px; 
    line-height: 327px; 
    height: 280px; 
    color: white; 
    -webkit-mask-image: -webkit-linear-gradient(top, rgba(0,0,0,0.2), rgba(0,0,0,1)); 
} 
.arc-overlay { 
    width: 100px; 
    height: 100px; 
    background-image: linear-gradient(bottom, rgb(217,217,217) 10%, rgb(245,245,245) 90%, rgb(253,253,253) 100%); 
    background-image: -o-linear-gradient(bottom, rgb(217,217,217) 10%, rgb(245,245,245) 90%, rgb(253,253,253) 100%); 
    background-image: -moz-linear-gradient(bottom, rgb(217,217,217) 10%, rgb(245,245,245) 90%, rgb(253,253,253) 100%); 
    background-image: -webkit-linear-gradient(bottom, rgb(217,217,217) 10%, rgb(245,245,245) 90%, rgb(253,253,253) 100%); 
 
    padding-left: 32px; 
    box-sizing: border-box; 
    -moz-box-sizing: border-box; 
    line-height: 100px; 
    font-family: sans-serif; 
    font-weight: 400; 
    text-shadow: 0 1px 0 #fff; 
    font-size: 22px; 
    border-radius: 100px; 
    position: absolute; 
    z-index: 5; 
    top: 75px; 
    left: 75px; 
    box-shadow:0px 0px 20px rgba(0,0,0,0.7); 
} 
.arc-container { 
    position: relative; 
    background: #e9e9e9; 
    height: 250px; 
    width: 250px; 
}
<div class="arc-container"> 
    <div class="arc-hider"></div> 
    <div class="arc-inset"> 
        o 
    </div> 
    <div class="arc-lowerInset"> 
        o 
    </div> 
    <div class="arc-overlay"> 
        35% 
    </div> 
    <div class="arc-wrapper"> 
        <div class="arc2"></div> 
        <div class="arc1"></div> 
    </div> 
</div>

Or this beautiful round progress bar with HTML5, CSS3 and JavaScript.

Answer 2

What about that?

HTML

<div class="chart" id="graph" data-percent="88"></div>

Javascript

var el = document.getElementById('graph'); // get canvas
var options = {
    percent:  el.getAttribute('data-percent') || 25,
    size: el.getAttribute('data-size') || 220,
    lineWidth: el.getAttribute('data-line') || 15,
    rotate: el.getAttribute('data-rotate') || 0
}
var canvas = document.createElement('canvas');
var span = document.createElement('span');
span.textContent = options.percent + '%';
if (typeof(G_vmlCanvasManager) !== 'undefined') {
    G_vmlCanvasManager.initElement(canvas);
}
var ctx = canvas.getContext('2d');
canvas.width = canvas.height = options.size;
el.appendChild(span);
el.appendChild(canvas);
ctx.translate(options.size / 2, options.size / 2); // change center
ctx.rotate((-1 / 2 + options.rotate / 180) * Math.PI); // rotate -90 deg
//imd = ctx.getImageData(0, 0, 240, 240);
var radius = (options.size - options.lineWidth) / 2;
var drawCircle = function(color, lineWidth, percent) {
        percent = Math.min(Math.max(0, percent || 1), 1);
        ctx.beginPath();
        ctx.arc(0, 0, radius, 0, Math.PI * 2 * percent, false);
        ctx.strokeStyle = color;
        ctx.lineCap = 'round'; // butt, round or square
        ctx.lineWidth = lineWidth
        ctx.stroke();
};
drawCircle('#efefef', options.lineWidth, 100 / 100);
drawCircle('#555555', options.lineWidth, options.percent / 100);

and CSS

div {
    position:relative;
    margin:80px;
    width:220px; height:220px;
}
canvas {
    display: block;
    position:absolute;
    top:0;
    left:0;
}
span {
    color:#555;
    display:block;
    line-height:220px;
    text-align:center;
    width:220px;
    font-family:sans-serif;
    font-size:40px;
    font-weight:100;
    margin-left:5px;
}

http://jsfiddle.net/Aapn8/3410/

Basic code was taken from Simple PIE Chart http://rendro.github.io/easy-pie-chart/

Answer 3

Another pure css based solution that is based on two clipped rounded elements that i rotate to get to the right angle:

http://jsfiddle.net/maayan/byT76/

That's the basic css that enables it:

.clip1 {
    position:absolute;
    top:0;left:0;
    width:200px;
    height:200px;
    clip:rect(0px,200px,200px,100px);
}
.slice1 {
    position:absolute;
    width:200px;
    height:200px;
    clip:rect(0px,100px,200px,0px);
    -moz-border-radius:100px;
    -webkit-border-radius:100px; 
    border-radius:100px;
    background-color:#f7e5e1;
    border-color:#f7e5e1;
    -moz-transform:rotate(0);
    -webkit-transform:rotate(0);
    -o-transform:rotate(0);
    transform:rotate(0);
}
.clip2 
{
    position:absolute;
    top:0;left:0;
    width:200px;
    height:200px;
    clip:rect(0,100px,200px,0px);
}
.slice2
{
    position:absolute;
    width:200px;
    height:200px;
    clip:rect(0px,200px,200px,100px);
    -moz-border-radius:100px;
    -webkit-border-radius:100px; 
    border-radius:100px;
    background-color:#f7e5e1;
    border-color:#f7e5e1;
    -moz-transform:rotate(0);
    -webkit-transform:rotate(0);
    -o-transform:rotate(0);
    transform:rotate(0);
}

and the js rotates it as required.

quite easy to understand..

Hope it helps, Maayan

Answer 4

Check this out :)

I made this one using conic-gradient.

background: conic-gradient(
      SomeColor1 80%,
      SomeColor2 80%
    );

You can create a pie chart using conic-gradient.

div {
  background: conic-gradient(
     red 36deg, orange 36deg 170deg, yellow 170deg);
  border-radius: 50%
}

I select only two colors for the pie chart.

  background: conic-gradient(
          rgb(3, 133, 255) 80%,
          rgb(242, 242, 242) 80%
        );

then place a div on top of the pie chart to make it looks like a circular progress indicator. Then set progress using HTML DOM innerHTML option.

Then you can use incrementProgress() and decrementProgress() fuctions to change progress dynamically.

Follow my complete example to get some idea :)

You can make upload/download progress indicators, charts for dashboards, etc. using this.

<html>
  <head>
    <style>
      body {
        display: flex;
        align-items: center;
        justify-content: center;
      }
      #progress-spinner {
        border-radius: 50%;
        height: 100px;
        width: 100px;
      }
      #middle-circle {
        position: absolute;
        border-radius: 50%;
        height: 80px;
        width: 80px;
        background-color: rgb(248, 248, 248);
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: large;
        font-weight: bold;
      }
    </style>
  </head>
  <body>
    <div
      style="
        position: relative;
        display: flex;
        justify-content: center;
        align-items: center;
        flex-direction: column;
      "
    >
      <div
        style="
          position: relative;
          display: flex;
          justify-content: center;
          align-items: center;
        "
      >
        <div id="middle-circle"></div>
        <div id="progress-spinner"></div>
      </div>
      <div style="margin-top: 30px">
        <button type="button" id="incbtn">+</button>
        <button type="button" id="decbtn">-</button>
      </div>
    </div>
    <script>
      var progress = 0;
      document
        .getElementById("incbtn")
        .addEventListener("click", incrementProgress);
      document
        .getElementById("decbtn")
        .addEventListener("click", decrementProgress);
      function incrementProgress() {
        if (progress != 100) {
          progress = progress + 10;
          console.log(progress);
          setProgress();
        }
      }
      function decrementProgress() {
        if (progress != 0) {
          progress = progress - 10;
          console.log(progress);
          setProgress();
        }
      }
      function setProgress() {
        document.getElementById("progress-spinner").style.background =
          "conic-gradient(rgb(3, 133, 255) " +
          progress +
          "%,rgb(242, 242, 242) " +
          progress +
          "%)";
        document.getElementById("middle-circle").innerHTML =
          progress.toString() + "%";
      }
      window.onload = function () {
        setProgress();
      };
    </script>
  </body>
</html>

Answer 5

Flexible SVG solution for radial progress-bar (CSS only): the solution in calculating(via calc) border length of circle inside SVG.

Progress-circle in samples is overlay on element, and may be transparent.

jQuery(function($){
 setTimeout(() => $('#element1 [data-role="radial-progress"]').css('--progress-percent', '100'), 1000);
 $('#element2 [data-role="radial-progress"]').css('--progress-percent', '80');
 $('#element3 [data-role="radial-progress"]').css('--progress-percent', '100');
 
 let progress4 = 0;
 let progress4incrementor = setInterval(() => {
  progress4++;
  $('#element4 .value').html(progress4 + '%');
  $('#element4 [data-role="radial-progress"]').css('--progress-percent', progress4.toString());
  if (progress4 >= 100) clearInterval(progress4incrementor);
 }, 100);
});
.element
{
  position: relative;
}
[data-role="radial-progress"]
{
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    z-index: 1;
    --progress-percent: 0;
  --progress-color: #CC000077;
  --progress-bar-width: 100%;
}
[data-role="radial-progress"] > circle
{
    stroke-width: var(--progress-bar-width);
    stroke-dasharray: calc(100% * 3.141592);
    stroke-dashoffset: calc(100% * (100 - var(--progress-percent))/100 * 3.141592);
    stroke: var(--progress-color);
}

/*Just for animate --data-percent */
#element1 [data-role="radial-progress"] > circle
{
  transition: stroke-dashoffset 4s linear;
}
#element2 [data-role="radial-progress"] > circle
{
  transition: stroke-dashoffset 2s linear;
}
#element3 [data-role="radial-progress"] > circle
{
  transition: stroke-dashoffset 6s linear;
}
#element4 [data-role="radial-progress"] > circle
{
  transition: stroke-dashoffset 0.1s linear;
}
/*–°ode that does not depend on radial-progress*/
.element
{
  background-image: url(https://static.wikia.nocookie.net/dune/images/2/2f/Duneii-wind-trap.jpg/revision/latest);
  background-size: 100% 100%;
  display: inline-block;
  width: 180px;
  height: 110px;
  border: 2px solid red;
  text-align: center;
  color: red;
}
#element3
{
  width: 110px;
}
#element3 [data-role="radial-progress"]
{
  transform: rotate(-90deg);
}
#element4
{
 display: inline-flex;
 align-items: center;
 justify-content: center;
}
#element4 .value
{
   font-size: 2em;
   font-weight: bold;
   z-index: 2;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="element1" class="element">
  Content
  <svg data-role="radial-progress" width="100%" height="100%" viewPort="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg"><circle r="50%" cx="50%" cy="50%" fill="transparent"></circle></svg>
</div>
<div id="element2" class="element">
  Content
  <svg style="--progress-percent:30" data-role="radial-progress" width="100%" height="100%" viewPort="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg"><circle r="50%" cx="50%" cy="50%" fill="transparent"></circle></svg>
</div>

<div id="element3" class="element">
  Content
  <svg style="--progress-bar-width:10px;--progress-color:red;" data-role="radial-progress" width="100%" height="100%" viewPort="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg"><circle r="44%" cx="50%" cy="50%" fill="transparent"></circle></svg>
</div>
<div id="element4" class="element">
  <span class="value">0%</span>
  <svg data-role="radial-progress" width="100%" height="100%" viewPort="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg"><circle r="50%" cx="50%" cy="50%" fill="transparent"></circle></svg>
</div>

Rent Charter Buses Company
READ ALSO
Simple templating system with {{field}} in PHP

Simple templating system with {{field}} in PHP

I'm designing a simple templating system for a CMS in PHP which internally currently uses something like:

127
jQuery Toggle Class on &quot;a&quot; Link Hover

jQuery Toggle Class on "a" Link Hover

I have a custom cursor div which changes when hovering over various elementsSo far, I have the cursor expanding on hover of

124
Increase Bidding Rate On Assests In Opensea-js

Increase Bidding Rate On Assests In Opensea-js

everyone so I have been working on a Bidding Bot to make Offers on Assests of a Collection on Openseaio

103
Batch job got 1205 &quot;Lock wait timeout exceeded&quot; error

Batch job got 1205 "Lock wait timeout exceeded" error

I have a batch with many jobs almost over 9,000 and the first of them consumed by workers always get 1205 "Lock wait timeout exceeded" errorsI have submitted an issue on GitHub but it was closed so I'm asking for help here

197