Just like the above image or an idea or reference to achieve this design, I appreciate the help or suggestion given by community thank you
I have got reference of progress bar which is circular but not able find an approach to solve it.
const boxes = document.querySelectorAll(".box");
const colors = ['red', 'blue', 'green', 'yellow', 'orange', 'violet']
boxes.forEach((box) => {
const insideContent = box.innerText;
box.style.border = `6px solid ${colors[insideContent]}`
})
#app {
display: flex;
}
.box {
width: 50px;
height: 50px;
margin: 10px;
background-color: cyan;
display: flex;
justify-content: center;
align-items: center;
}
<div id="app">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
</div>
As per your question I think this is what you are trying to achieve.
First define a pseudo class root
:root {
--color-val: blue;
}
Note: In order to use the --color-val you need to write it as color: var(--color-var) in CSS
Second use JavaScript to update the variable --color-val
let colors =
var root = document.querySelector(':root');
const delay = ms => new Promise(res => setTimeout(res, ms));
const colorChange = async () => {
await delay(1000);
color = colors[Math.floor(Math.random() * colors.length)]
console.log(color)
root.style.setProperty('--color-val', color);
};
colorChange()
Note:
Add the color list you want to select from or go to CodePen for a list of 1000+ hex codes.
Promise are used for asynchronous function and can be skipped by using setTimeOut for a delayed loop or if used with another eventlistener.
I apologize if I misunderstood the question. Wrote in a hurry and without beautyful visualisation, if you disassemble the principle, you can customize it.
h1 {
display: block;
margin:0 auto;
text-align: center;
padding-top:20%;
}
.container {
display:flex;
width: 150px;
height: 150px;
border: 1px solid black;
z-index: 110;
margin:0;
margin: -10px;
}
.top {
display:block;
background-color: green;
height: 24px;
width: 150px; /* gorizontal top */
animation: top 1s linear;
animation-fill-mode: forwards;
}
#keyframes top {
0% {
width: 0px;
}
100% {
width: 150px;
}
}
.right {
background-color: green;
height: 0%;/* right */
width: 32px;
animation: right 1s linear;
animation-fill-mode: forwards;
animation-delay: 1s;
z-index: 10;
}
#keyframes right {
0% {
height: 0%;
}
100% {
height: 100%;
}
}
.box {
position: fixed;
top: 32.5px;
left: 32.5px;
width: 100px;
height: 100px;
border: 1px solid black;
margin: auto;
z-index: 120;
margin: -10px -10px;
}
.bottom {
position: absolute;
top: 123px;
left: 150px;
background-color: green;
width: 0px;
height: 27px;
z-index: 10;
animation: bottom 1s linear;
animation-fill-mode: forwards;
animation-delay: 2s;
/* animation-direction: reverse; */
}
#keyframes bottom {
0% {
transform: translate(0,0);
}
100% {
transform: translate(-250px,0);
-webkit-transform: translate(-250px,0); /** Safari & Chrome **/
-o-transform: translate(-250px,0); /** Opera **/
-moz-transform: translate(-250px,0); /** Firefox **/
width: 250px;
}
}
.left {
position: absolute;
top: 122px;
background-color: green;
width: 25px;
height: 0px;
animation: left 1s linear;
animation-fill-mode: forwards;
animation-delay: 3s;
}
#keyframes left {
0% {
transform: translate(0,0);
}
100% {
transform: translate(0,-250px);
-webkit-transform: translate(0,-250px); /** Safari & Chrome **/
-o-transform: translate(0,-250px); /** Opera **/
-moz-transform: translate(0,-250px); /** Firefox **/
height: 277px;
}
}
<div class='head'>
<div class='container'>
<div class='top'></div>
<div class='box'>
<h1 id='timer'>
1
</h1>
</div>
<div class='right'></div>
<div class='bottom'></div>
<div class='left'></div>
</div>
</div>
<script type="text/javascript">
init()
function init()
{
sec = 0;
setInterval(tick, 1000);
}
function tick()
{ if (sec<3) { sec++
document.getElementById("timer").
childNodes[0].nodeValue = sec;
} else {
clearInterval(0);
}
}
</script>
Also, instead of the SetInterval script, you can take values from your block width and height styles and output a mathematical calculation in h1 instead of a stopwatch.
upd: After your comment, I decided to do what I wrote about above. You can play with values and math, I add a snippet of another solution that changes the progress bar from the entered values within the entered range. (of course, it would be easier on react than on pure js)
function grade () {
let grade = +document.getElementById("grade").value;
let range = +document.getElementById("range").value;
document.getElementById("timer").innerHTML = `${grade}/${range}`;
progress(grade,range)
}
function progress (value, grade) {
document.getElementById('1').style.backgroundColor = `white`
document.getElementById("left").className = "noactive";
document.getElementById('top').style.width = `0%`
document.getElementById('right').style.height = `0%`
document.getElementById('bottom').style.width = `0%`
let GradeValuSide = grade/4;
if (value <= GradeValuSide) {
document.getElementById('top').style.width =
`${value/GradeValuSide*100}%`
} else if (value > GradeValuSide && value <= (GradeValuSide*2)) {
document.getElementById('top').style.width = `100%`
document.getElementById('right').style.height =
`${(value-GradeValuSide)/GradeValuSide*100}%`
} else if (value >= grade/2 && value < (grade/4)*3) {
document.getElementById('top').style.width = `100%`
document.getElementById('right').style.height = `100%`
document.getElementById('bottom').style.width =
`${((((value-(GradeValuSide*2)) / GradeValuSide) *100) / 100) *27}%`
} else if (value >= grade-(grade/4) /* && value < value + 1 */) {
document.getElementById('top').style.width = `100%`
document.getElementById('right').style.height = `100%`
document.getElementById('bottom').style.width = `100%`
document.getElementById('1').style.backgroundColor = `green`
document.getElementById("left").className = "left";
document.getElementById('left').style.height =
`${(40 - (40 * ((((value-(GradeValuSide*3)) * 100) / GradeValuSide)/ 100)))}%`
}
}
h1 {
font-size:20px;
position: absolute;
left: 40px;
display: block;
margin: 0 auto;
align-items: center;
padding-top:10%;
}
.container {
display:flex;
width: 150px;
height: 150px;
border: 1px solid black;
margin:0;
margin: -10px;
}
div.top {
display:block;
background-color: green;
height: 24px;
width: 0%; /* gorizontal top */
z-index:999;
}
div.right {
position:relative;
background-color: green;
height: 0%;/* right */
width: 32px;
z-index: 9999;
}
.box {
position: fixed;
top: 32.5px;
left: 32.5px;
background-color:white;
width: 100px;
height: 100px;
border: 1px solid black;
margin: auto;
z-index: 120;
margin: -10px -10px;
}
.wrap{
position: relative;
}
div.bottom {
position: absolute;
top: 123px;
background-color: green;
width: 0%; /* 27 = 100% */
height: 27px;
float: right;
right: 78vw;
z-index: 100;
}
div.left {
position: absolute;
background-color: white;
width: 23px;
height: 40%;
top: 23px;
bottom: 10px;
left: 0;
float: top;
}
div.noactive {
position: absolute;
background-color: white;
width: 23px;
height: 0%;
top: 23px;
bottom: 10px;
left: 0;
float: top;
}
.items {
margin-top: 50px;
text-align: center;
}
.grade,
.value {
height: 15px;
width: 50px;
align-items: center;
}
<div class='head'>
<div id='1' class='container'>
<div id='top' class='top'></div>
<div class='box'>
<h1 id='timer'>1</h1>
<div class='items'>
value<input id='grade' class='grade' type=number oninput="grade()"/>
range<input id='range' class='value' type=number oninput="grade()"/>
</div>
</div>
<div id='right' class='right'></div>
<div id='bottom' class='bottom'></div>
<div id='left' class='noactive'></div>
</div>
</div>
<script src='app.js'></script>
I have used the wheel of fortune code from how to draw a wheel of fortune?
I've modified function drawSector(sector,i) to drawImage on each sector like this:
function drawSector(sector, i) {
const ang = arc * i;
ctx.save();
// COLOR
ctx.beginPath();
ctx.fillStyle = sector.color;
ctx.moveTo(rad, rad);
ctx.arc(rad, rad, rad, ang, ang + arc);
ctx.lineTo(rad, rad);
ctx.fill();
// TEXT
ctx.translate(rad, rad);
ctx.rotate(ang + arc / 2);
if(!sector.label.includes('<img')){
ctx.textAlign = "right";
ctx.fillStyle = "#fff";
ctx.fillText(sector.label, rad-10, txtPositionY);
}
else{
// IMG
const div = document.createElement('div')
div.innerHTML = sector.label
const img = div.querySelector('img');
const ratio = img.width/img.height;
let imgMinH = (2*PI*55)/sectors.length; // // r=110/2
let imgMaxW = (rad-15) - 55;
let imgW = imgMinH*ratio;
let imgH = imgMinH;
let imgX = (rad-15)-imgW;
let imgY = (-imgH)/2;
let LX = (2*PI*imgX)/sectors.length;
if(imgW<imgMaxW){
while( (imgX>55) && (imgH<LX) && (imgW<imgMaxW) ){
imgW += 1;
imgH = imgW/ratio;
imgX = (rad-15)-imgW;
imgY = (-imgH)/2;
LX = (2*PI*imgX)/sectors.length;
}
}
else{
while( (imgX<55) || (imgH>LX) || (imgW>imgMaxW) ){
imgW -= 1;
imgH = imgW/ratio;
imgX = (rad-15)-imgW;
imgY = (-imgH)/2;
LX = (2*PI*imgX)/sectors.length;
}
}
console.log("ratio:"+ratio+'\n orgH:'+imgMinH+'\n imgW:'+imgW+'\nimgH:'+imgH+'\nLX:'+LX+'\nimgX:'+imgX+'\nimgY:'+imgY+'\nimgMaxW:'+imgMaxW);
ctx.drawImage(img, imgX, imgY, imgW, imgH);
}
ctx.restore();
};
but i can not calculate exactly about image width, height and position. Please see the images below:
How to calculate exactly image width, height, position to drawImage like this image below?
Thank you!
const button = document.querySelector('.ring__button');
const ring = document.querySelector('.ring__wrapper');
button.addEventListener('click', () => {
ring.classList.add('ring__wrapper--rotate')
})
:root {
--size: 300px;
}
.ring {
width: var(--size);
height: var(--size);
position: relative;
z-index: 1;
}
.ring__wrapper {
display: flex;
flex-wrap: wrap;
border-radius: 100%;
overflow: hidden;
transform-origin: 50% 50%;
position: relative;
width: inherit;
height: inherit;
}
.ring__wrapper--rotate {
animation: rotate 3s;
transform: rotate(990deg)
}
.ring__button {
position: absolute;
z-index: 1;
border: none;
width: calc(var(--size) / 3);
height: calc(var(--size) / 3);
border-radius: 100%;
background: red;
display: flex;
align-items: center;
justify-content: center;
color: #ffffff;
font-weight: bold;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.ring__button:after {
position: absolute;
z-index: 3;
display: block;
content: '';
left: 50%;
bottom: 100%;
border-bottom: 20px solid red;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
transform: translate(-50%, 5%);
}
.ring__part {
width: calc(var(--size) / 2);
height: var(--size);
overflow: hidden;
}
.ring__part img {
width: inherit;
height: inherit;
object-fit: contain;
}
.ring__part--1 {background: aquamarine;}
.ring__part--1 img {transform: rotate(180deg);}
.ring__part--2 {background: antiquewhite;}
#keyframes rotate {
from {transform: rotate(0)}
to {transform: rotate(990deg)}
}
<div class="ring">
<button class="ring__button">QUAY</button>
<div class="ring__wrapper">
<div class="ring__part ring__part--1"><img src="https://images.unsplash.com/photo-1655810120657-9ce44d2f9e6c?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHwxOXx8fGVufDB8fHx8&auto=format&fit=crop&w=800&q=60" alt=""></div>
<div class="ring__part ring__part--2"><img src="https://images.unsplash.com/photo-1655810120657-9ce44d2f9e6c?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHwxOXx8fGVufDB8fHx8&auto=format&fit=crop&w=800&q=60" alt=""></div>
</div>
</div>
canvas is cool, but what about css?
const button = document.querySelector('.ring__button');
const ring = document.querySelector('.ring__wrapper');
button.addEventListener('click', () => {
ring.classList.add('ring__wrapper--rotate')
})
:root {
--size: 300px;
}
.ring {
width: var(--size);
height: var(--size);
position: relative;
z-index: 1;
}
.ring__wrapper {
display: flex;
flex-wrap: wrap;
border-radius: 100%;
overflow: hidden;
transform-origin: 50% 50%;
position: relative;
width: inherit;
height: inherit;
}
.ring__wrapper--rotate {
animation: rotate 3s;
transform: rotate(855deg)
}
.ring__button {
position: absolute;
z-index: 1;
border: none;
width: calc(var(--size) / 3);
height: calc(var(--size) / 3);
border-radius: 100%;
background: red;
display: flex;
align-items: center;
justify-content: center;
color: #ffffff;
font-weight: bold;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.ring__button:after {
position: absolute;
z-index: 3;
display: block;
content: '';
left: 50%;
bottom: 100%;
border-bottom: 20px solid red;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
transform: translate(-50%, 5%);
}
.ring__part {
width: calc(var(--size) / 2);
height: calc(var(--size) / 2);
overflow: hidden;
}
.ring__part img {
width: inherit;
height: inherit;
object-fit: contain;
}
.ring__part--1 {background: aquamarine;}
.ring__part--1 img {transform: rotate(225deg);}
.ring__part--2 {background: antiquewhite;}
.ring__part--2 img {transform: rotate(-45deg);}
.ring__part--3 {background: brown;}
.ring__part--3 img {transform: rotate(135deg);}
.ring__part--4 {background: burlywood;}
.ring__part--4 img {transform: rotate(45deg);}
#keyframes rotate {
from {transform: rotate(0)}
to {transform: rotate(855deg)}
}
<div class="ring">
<button class="ring__button">QUAY</button>
<div class="ring__wrapper">
<div class="ring__part ring__part--1"><img src="https://images.unsplash.com/photo-1655810120657-9ce44d2f9e6c?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHwxOXx8fGVufDB8fHx8&auto=format&fit=crop&w=800&q=60" alt=""></div>
<div class="ring__part ring__part--2"><img src="https://images.unsplash.com/photo-1655810120657-9ce44d2f9e6c?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHwxOXx8fGVufDB8fHx8&auto=format&fit=crop&w=800&q=60" alt=""></div>
<div class="ring__part ring__part--3"><img src="https://images.unsplash.com/photo-1655810120657-9ce44d2f9e6c?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHwxOXx8fGVufDB8fHx8&auto=format&fit=crop&w=800&q=60" alt=""></div>
<div class="ring__part ring__part--4"><img src="https://images.unsplash.com/photo-1655810120657-9ce44d2f9e6c?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHwxOXx8fGVufDB8fHx8&auto=format&fit=crop&w=800&q=60" alt=""></div>
</div>
</div>
I'm trying to create an infinite horizontal "scroll" like a marquee effect (like this one, for example).
This is my code:
.parent {
border: 1px solid black;
width: 100%;
height: 2rem;
}
.container {
height: 100%;
display: flex;
padding-left: 10%;
border: 1px solid tomato;
animation: marquee 5s linear infinite;
}
#keyframes marquee {
0% {
transform: translate(0%, 0);
}
100% {
transform: translate(-100%, 0);
}
}
.child1 {
width: 10rem;
height: 100%;
background-color: #84B7DF;
}
.child2 {
width: 18rem;
height: 100%;
background-color: #f58db6;
}
.child3 {
width: 13rem;
height: 100%;
background-color: #ffc410;
}
.child4 {
width: 21rem;
height: 100%;
background-color: #C8E7C1;
}
<div class="parent">
<div class="container">
<div class="child1"></div>
<div class="child2"></div>
<div class="child3"></div>
<div class="child4"></div>
</div>
</div>
As you can see, it works but not perfectly.
I would like that as soon as the green rectangle has shifted, the blue (slightly spaced) one immediately appears, I don't want there to ever be a whole white screen.
I hope is clear what I mean...
Thanks a lot!
You could just add one more container element with same children, and then use display: flex with overflow: hidden on parent element. Also you can set width of the .container element to be larger then the window width using vw units and flex property.
Adjust width and padding properties on container if you have to.
.parent {
border: 1px solid black;
width: 100%;
height: 2rem;
display: flex;
overflow: hidden;
}
.container {
height: 100%;
flex: 0 0 120vw;
display: flex;
padding-right: 10%;
border: 1px solid tomato;
animation: marquee 5s linear infinite;
}
#keyframes marquee {
0% {
transform: translate(0%, 0);
}
100% {
transform: translate(-100%, 0);
}
}
.child1 {
width: 10rem;
height: 100%;
background-color: #84B7DF;
}
.child2 {
width: 18rem;
height: 100%;
background-color: #f58db6;
}
.child3 {
width: 13rem;
height: 100%;
background-color: #ffc410;
}
.child4 {
width: 21rem;
height: 100%;
background-color: #C8E7C1;
}
<div class="parent">
<div class="container">
<div class="child1"></div>
<div class="child2"></div>
<div class="child3"></div>
<div class="child4"></div>
</div>
<div class="container other">
<div class="child1"></div>
<div class="child2"></div>
<div class="child3"></div>
<div class="child4"></div>
</div>
</div>
Another solution is to add padding-right width vw units on container.
.parent {
border: 1px solid black;
width: 100%;
height: 2rem;
display: flex;
overflow: hidden;
}
.container {
height: 100%;
display: flex;
padding-right: 50vw;
border: 1px solid tomato;
animation: marquee 5s linear infinite;
}
#keyframes marquee {
0% {
transform: translate(0%, 0);
}
100% {
transform: translate(-100%, 0);
}
}
.child1 {
width: 10rem;
height: 100%;
background-color: #84B7DF;
}
.child2 {
width: 18rem;
height: 100%;
background-color: #f58db6;
}
.child3 {
width: 13rem;
height: 100%;
background-color: #ffc410;
}
.child4 {
width: 21rem;
height: 100%;
background-color: #C8E7C1;
}
<div class="parent">
<div class="container">
<div class="child1"></div>
<div class="child2"></div>
<div class="child3"></div>
<div class="child4"></div>
</div>
<div class="container other">
<div class="child1"></div>
<div class="child2"></div>
<div class="child3"></div>
<div class="child4"></div>
</div>
</div>
Javascript / jQuery solution, you can first create clone of the original element and append it to parent. Create a function that will decrease left position of the elements with setInterval function. If the offset is less then -width of the same element that means that element is off the screen. In that case you should move element to the end of the window or to the end of the other element with some offset.
const parent = $(".parent");
const container = $(".container");
const offset = 250;
const clone = cloner(container, parent, offset);
function cloner(element, parent, offset) {
const clone = element.clone();
const width = element.width();
clone.css({left: width + offset})
parent.append(clone)
return clone;
}
function move(element, size = 1) {
const position = element.position().left;
const width = element.width();
if (position < -width) {
const next = element.siblings().first();
const nPosition = next.position().left;
const nWidth = next.width();
const wWidth = $(window).width();
if (nPosition + nWidth < wWidth) {
element.css({left: wWidth})
} else {
element.css({left: nPosition + nWidth + offset})
}
} else {
element.css({left: position - size})
}
}
window.mover = setInterval(() => {
move(container)
move(clone)
}, 5)
.parent {
border: 1px solid black;
width: 100%;
height: 2rem;
display: flex;
overflow: hidden;
position: relative;
}
.parent>div {
position: absolute;
left: 0;
}
.container {
height: 100%;
display: flex;
border: 1px solid tomato;
}
.child1 {
width: 10rem;
height: 100%;
background-color: #84B7DF;
}
.child2 {
width: 18rem;
height: 100%;
background-color: #f58db6;
}
.child3 {
width: 13rem;
height: 100%;
background-color: #ffc410;
}
.child4 {
width: 21rem;
height: 100%;
background-color: #C8E7C1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="parent">
<div class="container">
<div class="child1"></div>
<div class="child2"></div>
<div class="child3"></div>
<div class="child4"></div>
</div>
</div>
.marquee {
position: relative;
width: 100%;
height: 1.5em;
line-height: 1.5em;
overflow: hidden;
> div {
position: absolute;
display: flex;
flex-wrap: nowrap;
animation: marquee 10s linear infinite;
transform: translateX(100%);
> * {
display: inline;
white-space: nowrap;
&:last-child {
padding-right: 100%;
}
}
}
}
#keyframes marquee {
0% {
-moz-transform: translateX(100%);
-webkit-transform: translateX(100%);
transform: translateX(100%);
}
100% {
-moz-transform: translateX(-100%);
-webkit-transform: translateX(-100%);
transform: translateX(-100%);
}
}
I've picked a slider from codepen.io and made some changes in the code and when I paste it in the embed code of Weebly (the software where I'm working) it doesn't work, because it doesn't stop resizing and getting bigger and bigger. How can I stop it? P.S. I noticed it starts doing that when I insert the JavaScript code...
$(document).ready(function() {
var slide = $('.slide');
var viewWidth = $(window).width();
var viewHeight = $(window).height();
var sliderInner = $('.slider-inner');
var childrenNo = sliderInner.children().length
sliderInner.width(viewWidth * childrenNo);
// ----------- INITIAL -----------
function setWidth() {
slide.each(function() {
$(this).width(viewWidth);
$(this).css('left', viewWidth * $(this).index());
});
}
function setHeight() {
$('.loading').css('height', viewHeight);
$('.loading').css('line-height', $('.loading').css('height'));
$('.slider').css('height', viewHeight);
slide.each(function() {
$(this).css('line-height', $('.slider').css('height'));
});
}
setWidth();
setHeight();
// ----------- /INITIAL -----------
// ----------- RESIZE -----------
$(window).resize(function() {
viewWidth = $(window).width();
viewHeight = $(window).height();
setWidth();
setHeight();
sliderInner.css("transform", "translateX(-" +
$('.slider-nav>div.active').index() *
viewWidth + "px) translateZ(0)");
$('.slider-inner').width(viewWidth * childrenNo);
});
// ----------- /RESIZE -----------
// ----------- SET ACTIVE -----------
function setActive(element) {
var clickedIndex = element.index();
$('.slider-nav .active').removeClass('active');
element.addClass('active');
sliderInner.css("transform", "translateX(-" + clickedIndex * (viewWidth * 0.33) + "px) translateZ(0)");
//translateZ(0)
$('.slider-inner .active').removeClass('active');
$('.slider-inner .slide').eq(clickedIndex).addClass('active');
}
// ON CLICK NAV
$('.slider-nav > div').on('click', function() {
setActive($(this));
});
// LEFT - CLICK
$('.slider-control.left').on('click', function() {
var indexPos = $('.slider-nav>div.active').index();
if (indexPos > 0) {
--indexPos;
} else {
indexPos = childrenNo - 1;
}
setActive($('.slider-nav > div').eq(indexPos));
});
// RIGHT - CLICK
$('.slider-control.right').on('click', function() {
var indexPos = $('.slider-nav>div.active').index();
if (indexPos == childrenNo - 1) {
indexPos = 0;
} else {
++indexPos;
}
setActive($('.slider-nav > div').eq(indexPos));
});
// LOADING
setTimeout(function() {
$(".slider").fadeIn(500);
}, 500);
});
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: "Roboto", sans-serif;
font-weight: 300;
}
.head {
position: fixed;
top: 0;
left: 0;
z-index: 9;
padding: 40px;
color: #fff;
}
.head h1 {
font-weight: 300;
font-size: 4em;
}
.head p.author {
text-align: right;
}
.head p.console {
font-size: 10px;
color: #fff;
}
.loading {
background-color: #2ecc71;
width: 100%;
position: absolute;
top: 0;
left: 0;
height: 500px;
line-height: 500px;
text-align: center;
color: #fff;
font-size: 2rem;
}
.slider {
background-color: #fff;
position: relative;
width: 100%;
height: 500px;
overflow: hidden;
display: none;
}
.slider .slider-control {
height: 100%;
width: 100px;
background-color: #fff;
opacity: 0.01;
position: absolute;
top: 0;
z-index: 20;
cursor: pointer;
-webkit-transition-property: opacity;
transition-property: opacity;
-webkit-transition-duration: 0.25s;
transition-duration: 0.25s;
-webkit-transition-delay: 0;
transition-delay: 0;
-webkit-transition-timing-function: ease-in;
transition-timing-function: ease-in;
}
.slider .slider-control:hover {
opacity: 0.2;
}
.slider .left {
left: 0;
}
.slider .right {
right: 0;
}
.slider .slider-inner {
position: absolute;
left: 0;
top: 0;
height: 100%;
background-visibility: hidden;
-webkit-transition-duration: 0.5s;
transition-duration: 0.5s;
}
.slider .slider-inner .slide {
position: absolute;
top: 0;
height: 100%;
background-color: #f1c40f;
text-align: center;
line-height: 500px;
font-size: 5rem;
color: #fff;
}
.slider .slider-inner .slide.active {
-webkit-transform: scale(1, 1);
transform: scale(1, 1);
-webkit-transition-delay: 1s;
transition-delay: 1s;
}
.slider .slider-inner .slide:nth-child(2n) {
background-color: #2ecc71;
}
.slider .slider-inner .slide:nth-child(3n) {
background-color: #3498db;
}
.slider .slider-inner .slide:nth-child(4n) {
background-color: #9b50ba;
}
.slider-nav {
position: absolute;
bottom: 0;
left: 50%;
-webkit-transform: translateX(-50%);
transform: translateX(-50%);
padding: 5px;
padding-bottom: 20px;
text-align: center;
}
.slider-nav>div {
float: left;
width: 20px;
height: 20px;
border: 1px solid #fff;
z-index: 2;
display: inline-block;
margin: 0 15px;
cursor: pointer;
border-radius: 50%;
opacity: 0.5;
-webkit-transition-duration: 0.25s;
transition-duration: 0.25s;
background-color: transparent;
}
.slider-nav>div:hover {
opacity: 1;
}
.slider-nav>div.active {
background-color: white;
-webkit-transform: scale(1.5);
transform: scale(1.5);
opacity: 1;
}
.long {
height: 2000px;
width: 100%;
background-color: #2ecc71;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="head">
<h1>Gummy Slider</h1>
<p class="console">test console</p>
</div>
<div class="loading">
<p>Loading...</p>
</div>
<div class="slider">
<div class="slider-control left"></div>
<div class="slider-control right"></div>
<div class="slider-inner">
<div class="slide active">1</div>
<div class="slide">2</div>
<div class="slide">3</div>
<div class="slide">4</div>
<div class="slide">5</div>
<div class="slide">6</div>
<div class="slide">7</div>
<div class="slide">8</div>
</div>
<div class="slider-nav">
<div class="active"></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>
<div class="long"></div>
<script type="text/javascript">
Thanks,
Tom
You forgot a </script> in your code and that is probably the issue here. I tried this myself and it worked great.
Try the following:
<html>
<head>
<script
src="https://code.jquery.com/jquery-3.1.1.min.js"
integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8="
crossorigin="anonymous"></script>
</head>
<body>
<div class="head">
<h1>Gummy Slider</h1>
<p class="console">test console</p>
</div>
<div class="loading">
<p>Loading...</p>
</div>
<div class="slider">
<div class="slider-control left"></div>
<div class="slider-control right"></div>
<div class="slider-inner">
<div class="slide active">1</div>
<div class="slide">2</div>
<div class="slide">3</div>
<div class="slide">4</div>
<div class="slide">5</div>
<div class="slide">6</div>
<div class="slide">7</div>
<div class="slide">8</div>
</div>
<div class="slider-nav">
<div class="active"></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>
<div class="long"></div>
<script type="text/javascript">
$(document).ready(function(){
var slide = $('.slide');
var viewWidth = $(window).width();
var viewHeight = $(window).height();
var sliderInner = $('.slider-inner');
var childrenNo = sliderInner.children().length
sliderInner.width( viewWidth * childrenNo);
// ----------- INITIAL -----------
function setWidth() {
slide.each(function(){
$(this).width(viewWidth);
$(this).css('left', viewWidth * $(this).index());
});
}
function setHeight(){
$('.loading').css('height', viewHeight);
$('.loading').css('line-height', $('.loading').css('height'));
$('.slider').css('height', viewHeight);
slide.each(function(){
$(this).css('line-height', $('.slider').css('height'));
});
}
setWidth();
setHeight();
// ----------- /INITIAL -----------
// ----------- RESIZE -----------
$(window).resize(function(){
viewWidth = $(window).width();
viewHeight = $(window).height();
setWidth();
setHeight();
sliderInner.css("transform", "translateX(-" +
$('.slider-nav>div.active').index() *
viewWidth + "px) translateZ(0)");
$('.slider-inner').width( viewWidth * childrenNo);
});
// ----------- /RESIZE -----------
// ----------- SET ACTIVE -----------
function setActive(element) {
var clickedIndex = element.index();
$('.slider-nav .active').removeClass('active');
element.addClass('active');
sliderInner.css("transform", "translateX(-" + clickedIndex * (viewWidth * 0.33) + "px) translateZ(0)");
//translateZ(0)
$('.slider-inner .active').removeClass('active');
$('.slider-inner .slide').eq(clickedIndex).addClass('active');
}
// ON CLICK NAV
$('.slider-nav > div').on('click', function(){
setActive($(this));
});
// LEFT - CLICK
$('.slider-control.left').on('click', function(){
var indexPos = $('.slider-nav>div.active').index();
if (indexPos > 0) { --indexPos;
} else { indexPos = childrenNo-1; }
setActive($('.slider-nav > div').eq(indexPos));
});
// RIGHT - CLICK
$('.slider-control.right').on('click', function(){
var indexPos = $('.slider-nav>div.active').index();
if (indexPos == childrenNo-1) { indexPos = 0;
} else { ++indexPos; }
setActive($('.slider-nav > div').eq(indexPos));
});
// LOADING
setTimeout(function(){
$(".slider").fadeIn(500);
}, 500);
});
</script>
<style type="text/css">
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: "Roboto", sans-serif;
font-weight: 300;
}
.head {
position: fixed;
top: 0;
left: 0;
z-index: 9;
padding: 40px;
color: #fff;
}
.head h1 {
font-weight: 300;
font-size: 4em;
}
.head p.author {
text-align: right;
}
.head p.console {
font-size: 10px;
color: #fff;
}
.loading {
background-color: #2ecc71;
width: 100%;
position: absolute;
top: 0;
left: 0;
height: 500px;
line-height: 500px;
text-align: center;
color: #fff;
font-size: 2rem;
}
.slider {
background-color: #fff;
position: relative;
width: 100%;
height: 500px;
overflow: hidden;
display: none;
}
.slider .slider-control {
height: 100%;
width: 100px;
background-color: #fff;
opacity: 0.01;
position: absolute;
top: 0;
z-index: 20;
cursor: pointer;
-webkit-transition-property: opacity;
transition-property: opacity;
-webkit-transition-duration: 0.25s;
transition-duration: 0.25s;
-webkit-transition-delay: 0;
transition-delay: 0;
-webkit-transition-timing-function: ease-in;
transition-timing-function: ease-in;
}
.slider .slider-control:hover {
opacity: 0.2;
}
.slider .left {
left: 0;
}
.slider .right {
right: 0;
}
.slider .slider-inner {
position: absolute;
left: 0;
top: 0;
height: 100%;
background-visibility: hidden;
-webkit-transition-duration: 0.5s;
transition-duration: 0.5s;
}
.slider .slider-inner .slide {
position: absolute;
top: 0;
height: 100%;
background-color: #f1c40f;
text-align: center;
line-height: 500px;
font-size: 5rem;
color: #fff;
}
.slider .slider-inner .slide.active {
-webkit-transform: scale(1, 1);
transform: scale(1, 1);
-webkit-transition-delay: 1s;
transition-delay: 1s;
}
.slider .slider-inner .slide:nth-child(2n) {
background-color: #2ecc71;
}
.slider .slider-inner .slide:nth-child(3n) {
background-color: #3498db;
}
.slider .slider-inner .slide:nth-child(4n) {
background-color: #9b50ba;
}
.slider-nav {
position: absolute;
bottom: 0;
left: 50%;
-webkit-transform: translateX(-50%);
transform: translateX(-50%);
padding: 5px;
padding-bottom: 20px;
text-align: center;
}
.slider-nav > div {
float: left;
width: 20px;
height: 20px;
border: 1px solid #fff;
z-index: 2;
display: inline-block;
margin: 0 15px;
cursor: pointer;
border-radius: 50%;
opacity: 0.5;
-webkit-transition-duration: 0.25s;
transition-duration: 0.25s;
background-color: transparent;
}
.slider-nav > div:hover {
opacity: 1;
}
.slider-nav > div.active {
background-color: white;
-webkit-transform: scale(1.5);
transform: scale(1.5);
opacity: 1;
}
.long {
height: 2000px;
width: 100%;
background-color: #2ecc71;
}
</style>
</body></html>
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?
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.
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/
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>
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
A minimalistic approach using just one element and a couple of attributes:
Use data-progress to define the internal label and --progress to define the progress from 0deg to 360deg.
<div data-progress="36" style="--progress: 36deg;">36%</div>
div {
display: flex;
width: 100px;
height: 100px;
border-radius: 50%;
background: conic-gradient(red var(--progress), gray 0deg);
font-size: 0;
}
div::after {
content: attr(data-progress) '%';
display: flex;
justify-content: center;
flex-direction: column;
width: 100%;
margin: 10px;
border-radius: 50%;
background: white;
font-size: 1rem;
text-align: center;
}
<div data-progress="36" style="--progress: 36deg;">36%</div>
Here's a naïve approach to the animation, again all CSS, no JS and just one element:
div {
display: flex;
width: 100px;
height: 100px;
border-radius: 50%;
background: conic-gradient(red var(--progress), gray 0deg);
font-size: 0;
animation: .4s ease-out turn_in reverse;
}
div::after {
content: attr(data-progress);
display: flex;
justify-content: center;
flex-direction: column;
width: 100%;
margin: 10px;
border-radius: 50%;
background: white;
font-size: 1rem;
text-align: center;
}
#keyframes turn_in {
5% {
background: conic-gradient(red calc(var(--progress) * .95), gray 0deg);
}
10% {
background: conic-gradient(red calc(var(--progress) * .9), gray 0deg);
}
15% {
background: conic-gradient(red calc(var(--progress) * .85), gray 0deg);
}
20% {
background: conic-gradient(red calc(var(--progress) * .8), gray 0deg);
}
25% {
background: conic-gradient(red calc(var(--progress) * .75), gray 0deg);
}
30% {
background: conic-gradient(red calc(var(--progress) * .7), gray 0deg);
}
35% {
background: conic-gradient(red calc(var(--progress) * .65), gray 0deg);
}
40% {
background: conic-gradient(red calc(var(--progress) * .6), gray 0deg);
}
45% {
background: conic-gradient(red calc(var(--progress) * .55), gray 0deg);
}
50% {
background: conic-gradient(red calc(var(--progress) * .5), gray 0deg);
}
55% {
background: conic-gradient(red calc(var(--progress) * .45), gray 0deg);
}
60% {
background: conic-gradient(red calc(var(--progress) * .4), gray 0deg);
}
65% {
background: conic-gradient(red calc(var(--progress) * .35), gray 0deg);
}
70% {
background: conic-gradient(red calc(var(--progress) * 0.3), gray 0deg);
}
75% {
background: conic-gradient(red calc(var(--progress) * 0.25), gray 0deg);
}
80% {
background: conic-gradient(red calc(var(--progress) * .2), gray 0deg);
}
85% {
background: conic-gradient(red calc(var(--progress) * .15), gray 0deg);
}
90% {
background: conic-gradient(red calc(var(--progress) * .1), gray 0deg);
}
95% {
background: conic-gradient(red calc(var(--progress) * .05), gray 0deg);
}
100% {
background: conic-gradient(gray 0deg);
}
}
<div data-progress="85%" style="--progress: 85%;">85%</div>
Disclaimer: cross-browsing not tested.
A different idea with new #property. See the support table
#property --a {
syntax: '<angle>';
inherits: false;
initial-value: 90deg;
}
.circle {
width: 120px;
height: 120px;
padding: 12px;
box-sizing: border-box;
-webkit-mask:
conic-gradient(#000 var(--a), transparent var(--a)),
linear-gradient(#000, #000) content-box;
-webkit-mask-composite: source-out;
mask-composite: subtract;
background: tomato;
border-radius: 50%;
animation: progress 1s .3s linear forwards;
}
#keyframes progress {
to {
--a: 250deg;
}
}
<div class="circle"></div>
And I saw a more powerful example by Alvaro Montoro. Be sure to check this out.
acceding your data you can change process like <div ... data-num="50"> output 50% that go to the show fully animated circles and number.
change in data-num="/* 0-100 */".
you can add multiple process like 5,10.
using Javascript,CSS,Html with animated circle and number.
Output
Code
let items = document.querySelectorAll('.progress-item');
const counters = Array(items.length);
const intervals = Array(items.length);
counters.fill(0);
items.forEach((number,index) => {
intervals[index] = setInterval(() => {
if(counters[index] == parseInt(number.dataset.num)){
clearInterval(intervals[index]);
}else{
counters[index] += 1;
number.style.background = "conic-gradient(red calc(" + counters[index] + "%), gray 0deg)";
number.setAttribute('data-value', counters[index] + "%");
number.innerHTML = counters[index] + "%";
}
}, 15);
});
#progress{
display: flex;
justify-content: space-around;
}
.progress-item {
display: flex;
width: 100px;
height: 100px;
border-radius: 50%;
font-size: 0;
animation: .4s ease-out reverse;
}
.progress-item::after {
content: attr(data-value);
display: flex;
justify-content: center;
flex-direction: column;
width: 100px;
margin: 10px;
border-radius: 50%;
background: white;
font-size: 1rem;
text-align: center;
}
<div id="progress" >
<div data-num="40" class="progress-item">sd</div>
<div data-num="80" class="progress-item">sd</div>
<div data-num="57" class="progress-item">sd</div>
<div data-num="83" class="progress-item">sd</div>
<div data-num="90" class="progress-item">ds</div>
</div>
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>