0

I am unable to get the circle bar to animate. I attempted adding transition: all 600ms ease; but that didn't work. I am not sure if CSS animation supports conic-gradient.

jQuery(function ($) {
  $('.bar').addClass('animate');
});
.icon {
  width: 146px;
  height: 146px;
  padding: 36px;
  position: relative;
  flex-shrink: 0;
}
.icon .bar {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0px;
  left: 0px;
}
.icon .bar::before {
  content: "";
  position: absolute;
  border-radius: 50%;
  inset: 0;
  background: conic-gradient(#00a451 0%, #e1e1e1 0%);
  z-index: 1;
  transition: all 600ms ease;
}
.icon .bar::after {
  content: "";
  background-color: #fff;
  border-radius: 50%;
  width: 110px;
  height: 110px;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 2;
}
.icon .bar.animate::before {
  background: conic-gradient(#00a451 var(--stat-bar), #e1e1e1 0%);
}
<div class="icon">
  <div class="bar" style="--stat-bar:75%"></div>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>

4
  • Please go read How to Ask and minimal reproducible example, and then edit your question accordingly.
    – C3roe
    Commented Aug 26 at 11:49
  • @C3roe i was already editing my question while you was posting your comment. Commented Aug 26 at 11:54
  • 1
    You can't just transition CSS variables like that, you need to create a custom @property first - stackoverflow.com/a/74079080/1427878
    – C3roe
    Commented Aug 26 at 12:01
  • @C3roe I updated my script to what you advised but it broke my css. I am no longer able to see the green fill. I have updated the code snippet. Commented Aug 26 at 12:21

3 Answers 3

1

Fix: I have used the following https://codepen.io/t_afif/pen/XWaPXZO as an inspiration and updated my script accordingly and now it works as intended.

jQuery(function ($) {
  $('.module').addClass('animate');
});
@property --stat-bar{
  syntax: '<number>';
  inherits: true;
  initial-value: 0;
}

.icon{
  width: 146px;
  height: 146px;
  padding: 36px;
  position: relative;
  flex-shrink: 0;
}

.icon .bar {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0px;
  left: 0px;
}

.icon .bar:before {
  content: '';
  position: absolute;
  border-radius: 50%;
  inset: 0;
  background:
    radial-gradient(farthest-side, #00a451 98%, #0000) top/22px 22px no-repeat,
    conic-gradient(#00a451 calc(var(--stat-bar) * 1%), #0000 0);
  -webkit-mask: radial-gradient(farthest-side, #0000 calc(99% - 22px), #000 calc(100% - 22px));
  mask: radial-gradient(farthest-side, #0000 calc(99% - 22px), #000 calc(100% - 22px));
  background-size:
    0 0,
    auto;
}

.animate .icon .bar{
  animation:progress-bar 1s .5s both;
}
@keyframes progress-bar {
  from{--stat-bar:0}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>

<section class="module">
  <div class="icon">
      <div class="bar" style="--stat-bar:80;"></div>
  </div>
</section>

2
  • Is this an answer to your question? If so, please add an explanation. If not, delete it and edit your question
    – j08691
    Commented Aug 26 at 14:21
  • @j08691 i added a comment to the answer and to my question Commented Aug 26 at 14:29
0
  • Here I used your initial CSS and HTML as a starting point, trimmed CSS and HTML to the minimal necessary. All you need to add then is a CSS @property of <percentage> (or <number>) with an initial value of 0% that animates to any end-value stored inside an element's style="--data-bar:N%;" attribute.
  • PS: you don't need an entire jQuery library in order to assign classes to elements, and also you don't need the wrapping .icon element parent

document.querySelectorAll(".bar").forEach(el => el.classList.add("animate"));
@property --stat-bar {
  syntax: '<percentage>';
  inherits: true;
  initial-value: 0%;
}

.bar {
  display: inline-flex;
  position: relative;
  height: 150px;
  aspect-ratio: 1;
  inset: 0;
  mask: radial-gradient(#0000 32%, #000 calc(32% + 1px)); /* Hole */ 
  border-radius: 50%;

  &::before {
    content: "";
    position: absolute;
    inset: 0;
    background: conic-gradient(#00a451 var(--stat-bar), #e1e1e1 0%);
  }
  
  &.animate::before {
    animation: statBar 1s forwards;
  }
}

@keyframes statBar {
  from {
    --stat-bar: 0%;
  }
}
<div class="bar" style="--stat-bar:75%;"></div>
<div class="bar" style="--stat-bar:25%;"></div>

-1

With css animation not possible in this case, please see here for a reference.

I have implemented some extra code with the JS. Please review the attributes added animate-end="75" animate-speed="10".

$(function () {
  $(".bar").addClass("animate");
  var animationEnd = parseInt($(".bar").attr("animate-end"), 10);
  var speed = parseInt($(".bar").attr("animate-speed"), 10);
  var initial = 0;

  if (!isNaN(animationEnd) && animationEnd >= initial) {
    var intervalId = setInterval(() => {
      $(".bar").attr("style", `--stat-bar: ${initial}%`);
      initial++;

      if (initial > animationEnd) {
        clearInterval(intervalId);
      }
    }, speed);
  }
});
.icon {
    width: 146px;
    height: 146px;
    padding: 36px;
    position: relative;
    flex-shrink: 0;
}

.icon .bar {
    width: 100%;
    height: 100%;
    position: absolute;
    top: 0;
    left: 0;
}

.icon .bar::before {
    content: "";
    position: absolute;
    border-radius: 50%;
    inset: 0;
    background: conic-gradient(#00a451 0%, #e1e1e1 0%);
    z-index: 1;
    transition: none;
}

.icon .bar::after {
    content: "";
    background-color: #fff;
    border-radius: 50%;
    width: 110px;
    height: 110px;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    z-index: 2;
}

.icon .bar.animate::before {
    background: conic-gradient(#00a451 var(--stat-bar), #e1e1e1 0%);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<div class="icon">
    <div class="bar" animate-end="75" animate-speed="10"></div>
</div>

Please let me know if this could help you.

6
  • @DarkBee that's why mentioned in this case. Please let me know as well how we can sort this. Commented Aug 26 at 12:27
  • @MaheshThorat your solution seems to ignore the animation needing to be triggered when .animate class is added. You are forcing the animation with javascript. I am pretty sure this can be done via css like in this codepen codepen.io/t_afif/pen/XWaPXZO but I wasn't able to repurpose it to solve my problem. Commented Aug 26 at 12:35
  • @DarkBee I don't think there is a solution with dynamic width without using javascript. Your SO example says so. Temami solution is not dynamic. This is his fiddle on the same jsfiddle.net/a91ebko8/1. Even the blog post ends with, "You can use it as is, or you can extend it to suit your needs, sprinkling in a little bit of JavaScript if you need to" Do you have a css only solution? Commented Aug 26 at 12:39
  • 1
    @codeandcloud Unsure what you mean with dynamic width here? See the comment made by OP above as well - Mahesh just states it's not possible without giving an explanation why it wouldn't be possible.
    – DarkBee
    Commented Aug 26 at 12:47
  • @DarkBee I said only about this case. There are many more alternative you can try and implement. And why not working. Please see this url once Commented Aug 26 at 12:53

Not the answer you're looking for? Browse other questions tagged or ask your own question.