Drawing a tick mark in the progressbar if the process is done - html

I was created a simple progressbar with CSS & HTML. Here I used three classes active, inactive & done.
.container {
width: 600px;
margin: 100px auto;
}
.progressbar li {
list-style-type: none;
width: 25%;
float: left;
font-size: 12px;
position: relative;
text-align: center;
color: #7d7d7d;
}
.progressbar li:before {
width: 30px;
height: 30px;
content: "";
line-height: 30px;
border: 2px solid #7d7d7d;
display: block;
text-align: center;
margin: 0 auto 10px auto;
border-radius: 50%;
background-color: white;
}
.progressbar li:after {
width: 100%;
height: 2px;
content: '';
position: absolute;
background-color: #7d7d7d;
top: 15px;
left: -50%;
z-index: -1;
}
.progressbar li:first-child:after {
content: none;
}
.progressbar li.active {
color: green;
}
.progressbar li.active:before {
border-color: #55b776;
background-color: #55b776;
}
.progressbar li.active+li:after {
background-color: #55b776;
}
.progressbar li.done:before {
border-color: #55b776;
background-color: #55b776;
}
.progressbar li.done+li:after {
background-color: #55b776;
}
.progressbar li.inactive:before {
border-color: #7d7d7d;
background-color: #7d7d7d;
}
.progressbar li.inactive+li:after {
background-color: #7d7d7d;
}
<div class="container">
<ul class="progressbar">
<li class="done"></li>
<li class="active"></li>
<li class="inactive"></li>
</ul>
</div>
If the class is active it will show the circle with background-color: green,
If the class is inactive it will show the circle with background-color: grey
What i want is while using class 'done' i need to show the circle with background-color: green and tick mark inside the green circle like this. I tried a lot but not able to finish it. Please someone help me. Here is my working fiddle link

Use tick mark in content: "✓";
.container {
width: 600px;
margin: 100px auto;
}
.progressbar li {
list-style-type: none;
width: 25%;
float: left;
font-size: 12px;
position: relative;
text-align: center;
color: #7d7d7d;
}
.progressbar li:before {
width: 30px;
height: 30px;
content: "";
line-height: 30px;
border: 2px solid #7d7d7d;
display: block;
text-align: center;
margin: 0 auto 10px auto;
border-radius: 50%;
background-color: white;
}
.progressbar li.done:before {
content: "✓";
color: #ffffff;
font-size: 20px;
}
.progressbar li:after {
width: 100%;
height: 2px;
content: '';
position: absolute;
background-color: #7d7d7d;
top: 15px;
left: -50%;
z-index: -1;
}
.progressbar li:first-child:after {
content: none;
}
.progressbar li.active {
color: green;
}
.progressbar li.active:before {
border-color: #55b776;
background-color: #55b776;
}
.progressbar li.active + li:after {
background-color: #55b776;
}
.progressbar li.done:before {
border-color: #55b776;
background-color: #55b776;
}
.progressbar li.done + li:after {
background-color: #55b776;
}
.progressbar li.inactive:before {
border-color: #7d7d7d;
background-color: #7d7d7d;
}
.progressbar li.inactive + li:after {
background-color: #7d7d7d;
}
<div class="container">
<ul class="progressbar">
<li class="done"></li>
<li class="active"></li>
<li class="inactive"></li>
</ul>
</div>
As per your Requirements using css
.container {
width: 600px;
margin: 100px auto;
}
.progressbar li {
list-style-type: none;
width: 25%;
float: left;
font-size: 12px;
position: relative;
text-align: center;
color: #7d7d7d;
}
.progressbar li:before {
width: 30px;
height: 30px;
content: "";
line-height: 30px;
border: 2px solid #7d7d7d;
display: block;
text-align: center;
margin: 0 auto 10px auto;
border-radius: 50%;
background-color: white;
}
.progressbar li:after {
width: 100%;
height: 2px;
content: '';
position: absolute;
background-color: #7d7d7d;
top: 15px;
left: -50%;
z-index: -1;
}
.progressbar li:first-child:after {
content: none;
}
.progressbar li.active {
color: green;
}
.progressbar li.active:before {
border-color: #55b776;
background-color: #55b776;
}
.progressbar li.active + li:after {
background-color: #55b776;
}
.progressbar li.done:before {
border-color: #55b776;
background-color: #55b776;
}
.progressbar li.done + li:after {
background-color: #55b776;
}
.progressbar li.inactive:before {
border-color: #7d7d7d;
background-color: #7d7d7d;
}
.progressbar li.inactive + li:after {
background-color: #7d7d7d;
}
.progressbar li.done {
font-size: 16px;
position: relative;
}
.progressbar li.done:after {
content: " ";
display: block;
width: 0.3em;
height: 0.6em;
border: solid white;
border-width: 0 0.2em 0.2em 0;
position: absolute;
left: 4.2em;
top: 26%;
margin-top: -0.2em;
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-o-transform: rotate(45deg);
transform: rotate(45deg);
z-index:9;
background-color: #55b776;
}
<div class="container">
<ul class="progressbar">
<li class="done"></li>
<li class="active"></li>
<li class="inactive"></li>
</ul>
</div>

You only need to set the content to the tick mark when the done class is applied.
.progressbar li.done:before {
content: "✔";
}
Wirking fiddle: https://jsfiddle.net/ordmpf59/

Related

Responsive Progress Bar Vertical Alignment

I have a responsive multi step progress bar, link here and code snippet below;
.multi-steps > li.is-active:before, .multi-steps > li.is-active ~ li:before {
content: counter(stepNum);
font-family: inherit;
font-weight: 700;
}
.multi-steps > li.is-active:after, .multi-steps > li.is-active ~ li:after {
background-color: #ededed;
}
.multi-steps {
display: table;
table-layout: fixed;
width: 100%;
}
.multi-steps > li {
counter-increment: stepNum;
text-align: center;
display: table-cell;
position: relative;
color: tomato;
}
.multi-steps > li:before {
content: '\f00c';
content: '\2713;';
content: '\10003';
content: '\10004';
content: '\2713';
display: block;
margin: 0 auto 4px;
background-color: #fff;
width: 36px;
height: 36px;
line-height: 32px;
text-align: center;
font-weight: bold;
border-width: 2px;
border-style: solid;
border-color: tomato;
border-radius: 50%;
}
.multi-steps > li:after {
content: '';
height: 2px;
width: 100%;
background-color: tomato;
position: absolute;
top: 16px;
left: 50%;
z-index: -1;
}
.multi-steps > li:last-child:after {
display: none;
}
.multi-steps > li.is-active:before {
background-color: #fff;
border-color: tomato;
}
.multi-steps > li.is-active ~ li {
color: #808080;
}
.multi-steps > li.is-active ~ li:before {
background-color: #ededed;
border-color: #ededed;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container-fluid">
<br /><br />
<ul class="list-unstyled multi-steps">
<li>Start</li>
<li class="is-active">First Step</li>
<li>Middle Stage</li>
<li>Finish</li>
</ul>
</div>
This works fine but on smaller screens (e.g max-device-width: 480px), portrait mode i'd like to stack the steps vertically.
How can I achieve this?
Inside your media query, change display: table-cell to display: block on the .multi-steps > li element. That should get you close to what you want to achieve. You'll also need to apply some additional styling just to neat it out. Hope that helps.
e.g.
.multi-steps > li {
display: block;
}
Add a <span> element arounf the text, the use this CSS
.multi-steps > li {
display: block;
position: relative;
padding-bottom: 45px;
}
.multi-steps > li:before {
content: '\f00c';
content: '\2713;';
content: '\10003';
content: '\10004';
content: '\2713';
display: block;
margin: 0 auto 4px;
background-color: #fff;
width: 36px;
height: 36px;
line-height: 32px;
text-align: center;
font-weight: bold;
border-width: 2px;
border-style: solid;
border-color: tomato;
border-radius: 50%;
}
.multi-steps > li:after {
content: '';
height: 2px;
width: 100%;
background-color: tomato;
position: absolute;
left: 50%;
z-index: -1;
display: inline-block;
top: 0;
left: 50%;
width: 3px;
height: 105px;
}
.multi-steps > li span.step {
margin-left: 50px;
position: relative;
top: 20px;
}

Stepper Pure HTML CSS

I'm confused about a progress bar that I have created.
I want the progress bar to change its background color to blue after setting the class to “active”. But I want the progress bar to change its background color before the class is set to “active”.
Here is my HTML:
<ul class="progressBar">
<li class="active">Beong Processed</li>
<li class="active">Waiting for payment</li>
<li>Paid</li>
</ul>
…and CSS:
.progressBar li.active {
color: dodgerblue;
}
.progressBar li.active:before {
border-color: dodgerblue;
background-color: dodgerblue
}
.progressBar li.active + li:after {
background-color: dodgerblue;
}
The result is this
I want it to be like this
https://jsfiddle.net/dedi_wibisono17/c69e374r/2/
Use .progressBar .active:after
instead of .progressBar li.active + li:after
+ in css
It is Adjacent sibling combinator. It combines two sequences of simple
selectors having the same parent and the second one must come
IMMEDIATELY after the first.
.wrapper-progressBar {
width: 100%
}
.progressBar {
}
.progressBar li {
list-style-type: none;
float: left;
width: 33%;
position: relative;
text-align: center;
}
.progressBar li:before {
content: " ";
line-height: 30px;
border-radius: 50%;
width: 30px;
height: 30px;
border: 1px solid #ddd;
display: block;
text-align: center;
margin: 0 auto 10px;
background-color: white
}
.progressBar li:after {
content: "";
position: absolute;
width: 100%;
height: 4px;
background-color: #ddd;
top: 15px;
left: -50%;
z-index: -1;
}
.progressBar li:first-child:after {
content: none;
}
.progressBar li.active {
color: dodgerblue;
}
.progressBar li.active:before {
border-color: dodgerblue;
background-color: dodgerblue
}
.progressBar .active:after {
background-color: dodgerblue;
}
<div class="row">
<div class="col-xs-12 col-md-8 offset-md-2 block border">
<div class="wrapper-progressBar">
<ul class="progressBar">
<li class="active">Beong Processed</li>
<li class="active">Waiting for payment</li>
<li>Paid</li>
</ul>
</div>
</div>
</div>
According to what you requested, this is more like the answer you asked for?
.wrapper-progressBar {
width: 100%
}
.progressBar {
}
.progressBar li {
list-style-type: none;
float: left;
width: 33%;
position: relative;
text-align: center;
}
.progressBar li:before {
content: " ";
line-height: 30px;
border-radius: 50%;
width: 17px;
height: 17px;
border: 1px solid #ddd;
border-left:none;
display: block;
text-align: center;
margin: 8.5px auto 0px;
background-color: #eee;
}
.progressBar li:after {
content: "";
position: absolute;
width: 97%;
height: 5px;
background-color: #eee;
border: 1px solid #ddd;
border-right:none;
top: 15px;
left: -50%;
z-index: -1;
}
.progressBar li:first-child:after {
content: none;
}
.progressBar li.active {
color: dodgerblue;
}
.progressBar li.active:before {
border-color: dodgerblue;
background-color: dodgerblue
}
.progressBar .active:after {
background-color: dodgerblue;
}
<div class="row">
<div class="col-xs-12 col-md-8 offset-md-2 block border">
<div class="wrapper-progressBar">
<ul class="progressBar">
<li class="active">Beong Processed</li>
<li class="active">Waiting for payment</li>
<li>Paid</li>
</ul>
</div>
</div>
</div>
Try changing your .progressBar li.active + li:after selector to .progressBar li.active:after
.wrapper-progressBar {
width: 100%
}
.progressBar {
}
.progressBar li {
list-style-type: none;
float: left;
width: 33%;
position: relative;
text-align: center;
}
.progressBar li:before {
content: " ";
line-height: 30px;
border-radius: 50%;
width: 30px;
height: 30px;
border: 1px solid #ddd;
display: block;
text-align: center;
margin: 0 auto 10px;
background-color: white
}
.progressBar li:after {
content: "";
position: absolute;
width: 100%;
height: 2px;
background-color: #ddd;
top: 15px;
left: -50%;
z-index: -1;
}
.progressBar li:first-child:after {
content: none;
}
.progressBar li.active {
color: dodgerblue;
}
.progressBar li.active:before {
border-color: dodgerblue;
background-color: dodgerblue
}
.progressBar li.active:after {
background-color: dodgerblue;
}
<div class="row">
<div class="col-xs-12 col-md-8 offset-md-2 block border">
<div class="wrapper-progressBar">
<ul class="progressBar">
<li class="active">Beong Processed</li>
<li class="active">Waiting for payment</li>
<li>Paid</li>
</ul>
</div>
</div>
</div>

Creating CSS circle steps connected with lines from top to the bottom

I already figure out to do the circle steps horizontally. But to do like the picture below is quite stressful. Can you figure out how to do this?
Here is code
.container-progress {
margin: 100px auto;
font-size: 24px;
font-weight: bold;
font-family: Verdana;
color: white;
margin-top: 50px;
padding: 0;
}
.progressbar {
margin: 0;
padding: 0;
counter-reset: step;
}
.progressbar li {
list-style-type: none;
width: 16%;
float: left;
font-size: 12px;
position: relative;
text-align: center;
text-transform: uppercase;
}
.progressbar li:before {
width: 5em;
height: 5em;
content: counter(step);
counter-increment: step;
line-height: 90px;
border: 2px solid #7d7d7d;
display: block;
text-align: center;
margin: 0 auto 10px auto;
padding: 0;
border-radius: 50%;
background-color: black;
font-size: 18px;
font-weight: bold;
}
.progressbar li:after {
margin-top: 30px;
width: 100%;
height: .5em;
content: '';
position: absolute;
background-color: #7d7d7d;
top: 15px;
left: -50%;
z-index: -1;
}
.progressbar li:first-child:after {
content: none;
}
.progressbar li.active {
color: white;
}
.progressbar li.active:before {
border-color: dodgerblue;
background: dodgerblue;
}
.progressbar li.active+li:after {
/*background-color: dodgerblue;*/
}
.progressbar label {
color: black;
}
<div class="container-progress">
<ul class="progressbar">
<li class="active active-step">
<label>step 1</label>
</li>
<li>
<label>step 2</label>
</li>
<li>
<label>step 3</label>
</li>
<li>
<label>step 4</label>
</li>
<li>
<label>step 5</label>
</li>
<li>
<label>step 6</label>
</li>
</ul>
</div>
Fiddle link
This uses a border on the ul to create your connecting lines and uses position:absolute to position the individual steps. You will probably need to tweak it a bit more but it could get you moving in the right direction.
Edit
To get the first three label to appear above ther cirlces, swap :before with :after. I've updated my code to reflect this.
.container-progress {
margin: 100px auto;
font-size: 24px;
font-weight: bold;
font-family: Verdana;
color: white;
margin-top: 50px;
padding: 0;
}
.progressbar {
margin: 0 50px;
padding: 0;
counter-reset: step;
position:relative;
border: 2px solid #7d7d7d;
border-left:none;
min-height:200px;
}
.progressbar li {
list-style-type: none;
width: 16%;
/*float: left;*/
font-size: 12px;
position: absolute;
text-align: center;
text-transform: uppercase;
}
/*First Three*/
.progressbar li:nth-child(-n+3)
{
top:-45px
}
/*Last Three*/
.progressbar li:nth-last-child(-n+3)
{
bottom:-75px
}
/*Left*/
.progressbar li:nth-child(1), .progressbar li:nth-child(6)
{
left:-45px
}
/*Middle*/
.progressbar li:nth-child(2), .progressbar li:nth-child(5)
{
left:calc(50% - 45px);
}
/*Right*/
.progressbar li:nth-child(3), .progressbar li:nth-child(4)
{
left:calc(100% - 45px);
}
.progressbar li:nth-last-child(-n+3):before, .progressbar li:nth-child(-n+3):after {
width: 5em;
height: 5em;
content: counter(step);
counter-increment: step;
line-height: 90px;
border: 2px solid #7d7d7d;
display: block;
text-align: center;
margin: 0 auto 10px auto;
padding: 0;
border-radius: 50%;
background-color: black;
font-size: 18px;
font-weight: bold;
}
/*.progressbar li:after {
margin-top: 30px;
width: 100%;
height: .5em;
content: '';
position: absolute;
background-color: #7d7d7d;
top: 15px;
left: -50%;
z-index: -1;
}*/
/*.progressbar li:first-child:after {
content: none;
}*/
.progressbar li.active {
color: white;
}
.progressbar li.active:before, .progressbar li.active:after {
border-color: dodgerblue;
background: dodgerblue;
}
.progressbar li.active+li:after {
/*background-color: dodgerblue;*/
}
.progressbar label {
color: black;
}
<div class="container-progress">
<ul class="progressbar">
<li class="active active-step">
<label>step 1</label>
</li>
<li>
<label>step 2</label>
</li>
<li>
<label>step 3</label>
</li>
<li>
<label>step 4</label>
</li>
<li>
<label>step 5</label>
</li>
<li>
<label>step 6</label>
</li>
</ul>
</div>

Show progress half way in li using css

Something like below:
My Less looks as below at the moment.
/*progressbar*/
.progressbar {
margin-bottom: 30px;
margin-top: 10px;
counter-reset: step;
clear: both;
}
.progressbar li {
font-size: 12px;
width: 24%;
float: left;
position: relative;
text-align: center;
&:before {
content: counter(step);
counter-increment: step;
width: 25px;
line-height: 13px;
display: block;
font-size: 12px;
color: transparent;
border: 6px solid #ececec ;
background: #27ae60 ;
border-radius: 19px;
margin: 0 auto 4px;
}
&:after {
content: '';
width: 85%;
height: 3px;
background: #B9B9B9;
position: absolute;
left: -42%;
top: 10px;
z-index: 0;
}
&:first-child:after {
content: none;
}
}
.progress-payment li {
width: 50%;
}
.progressbar li.active{
&:after, &:before {
background: #success-btn;
color: #success-btn;
}
}
HTML
<ul class="progressbar">
<li class="active">Order Placed</li>
<li>Shipped</li>
<li>Completed</li>
<li>Settled</li>
</ul>
Please help
You can do this by using a linear-gradient background for the pseudo element that is producing the bar. The gradient is half-and-half, with completed color for first half and the pending color for rest.
/*progressbar*/
.progressbar {
margin-bottom: 30px;
margin-top: 10px;
counter-reset: step;
clear: both;
list-style: none;
}
.progressbar li {
font-size: 12px;
width: 24%;
float: left;
position: relative;
text-align: center;
}
.progressbar li:before {
content: counter(step);
counter-increment: step;
width: 25px;
line-height: 25px;
display: block;
font-size: 12px;
color: transparent;
border: 6px solid #ececec;
background: #27ae60;
border-radius: 19px;
margin: 0 auto 4px;
}
.progressbar li:after {
content: '';
width: 85%;
height: 3px;
background: #B9B9B9;
position: absolute;
left: -42%;
top: 17px;
z-index: -1;
}
.progressbar li:first-child:after {
content: none;
}
.progress-payment li {
width: 50%;
}
.progressbar li.active:after,
.progressbar li.active:before {
background: #27ae60;
color: white;
}
.progressbar li.complete:after {
background: #27ae60;
}
.progressbar li.half-complete:after {
background: linear-gradient(to right, #27ae60 50%, #B9B9B9 50%);
color: white;
}
<ul class="progressbar">
<li class="complete">Order Placed</li>
<li class="complete">Shipped</li>
<li class="active">Completed</li>
<li class="half-complete">Settled</li>
</ul>
If you want a slightly curved half-fill for the progress bar then you could use radial-gradient for the background like in the below snippet.
/*progressbar*/
.progressbar {
margin-bottom: 30px;
margin-top: 10px;
counter-reset: step;
clear: both;
list-style: none;
}
.progressbar li {
font-size: 12px;
width: 24%;
float: left;
position: relative;
text-align: center;
}
.progressbar li:before {
content: counter(step);
counter-increment: step;
width: 25px;
line-height: 25px;
display: block;
font-size: 12px;
color: transparent;
border: 6px solid #ececec;
background: #27ae60;
border-radius: 19px;
margin: 0 auto 4px;
}
.progressbar li:after {
content: '';
width: 85%;
height: 3px;
background: #B9B9B9;
position: absolute;
left: -42%;
top: 17px;
z-index: -1;
}
.progressbar li:first-child:after {
content: none;
}
.progress-payment li {
width: 50%;
}
.progressbar li.active:after,
.progressbar li.active:before {
background: #27ae60;
color: white;
}
.progressbar li.complete:after {
background: #27ae60;
}
.progressbar li.half-complete:after {
background: radial-gradient(50% 300% at 25% 50%, #27ae60 50%, #B9B9B9 40%);
color: white;
}
<ul class="progressbar">
<li class="complete">Order Placed</li>
<li class="complete">Shipped</li>
<li class="active">Completed</li>
<li class="half-complete">Settled</li>
</ul>
Note: Both the solutions assume that your target browsers are those that support gradients (IE10+).
Another approach is to use animation for this.
Since you are already using both pseudoelements in your list items. We will use a pseudoelement in the ul element to provide the empty progress line.
We will keep your other classes just for demo purposes but you can optimize this method way further. The principle would have to change to take into consideration the whole process from 0 to 100% from step 1 to 4, not to 1 to 2, 2 to 3, etc.
Here we go:
First we create our pseudoelement in the ul element just for the grey fallback.
.progressbar::after {
content: '';
width: 68%;
height: 3px;
background: #B9B9B9;
position: absolute;
left: 17%;
top: 17px;
z-index: -2;
}
Then we scale down the ::after pseudoelement of the list item to 0 in the main axis. (use one : if you are providing older browser support).
Here we are keeping your class just as a selector, like I previously said you can make this even better but it would require changing some logic.
Here we also declare an animation we will create in the next step. What will it do? It will just scale back to 1 our pseudoelement.
.progressbar li.half-complete:after {
transform: scaleX(0);
color: white;
animation: fill 100ms linear forwards;
background-color: #27ae60;
}
We define the keyframe:
#keyframes fill {
to {
transform: scaleX(1);
}
}
So far we get this:
/*progressbar*/
.progressbar {
margin-bottom: 30px;
margin-top: 10px;
counter-reset: step;
clear: both;
list-style: none;
position: relative;
}
.progressbar li {
font-size: 12px;
width: 24%;
float: left;
position: relative;
text-align: center;
}
.progressbar li:before {
content: counter(step);
counter-increment: step;
width: 25px;
line-height: 25px;
display: block;
font-size: 12px;
color: transparent;
border: 6px solid #ececec;
background: #27ae60;
border-radius: 19px;
margin: 0 auto 4px;
}
.progressbar li:after {
content: '';
width: 85%;
height: 3px;
position: absolute;
left: -42%;
top: 17px;
z-index: -1;
}
.progressbar::after {
content: '';
width: 68%;
height: 3px;
background: #B9B9B9;
position: absolute;
left: 17%;
top: 17px;
z-index: -2;
}
.progressbar li:first-child:after {
content: none;
}
.progress-payment li {
width: 50%;
}
.progressbar li.active:after,
.progressbar li.active:before {
background: #27ae60;
color: white;
}
.progressbar li.half-complete:before {
color: white;
}
.progressbar li.complete:after {
background: #27ae60;
}
.progressbar li.half-complete:after {
transform: scaleX(0);
color: white;
animation: fill 3s linear forwards;
background-color: #27ae60;
}
#keyframes fill {
to {
transform: scaleX(1);
}
}
<ul class="progressbar">
<li class="complete">Order Placed</li>
<li class="complete">Shipped</li>
<li class="active">Completed</li>
<li class="half-complete">Settled</li>
</ul>
We are not quite there yet, we got the animation, but it starts from the center and we want a specific frame, when the bar is at 50%.
Since the browser creates multiple frames when you create an animation, you can get the one you want with the property animation-delay, normally you would use a positive value, but when you use a negative one, the animation starts from that point.
Lets make the animation start from the left with transform-origin: left and finish all the way to the right without using animation-delay yet:
/*progressbar*/
.progressbar {
margin-bottom: 30px;
margin-top: 10px;
counter-reset: step;
clear: both;
list-style: none;
position: relative;
}
.progressbar li {
font-size: 12px;
width: 24%;
float: left;
position: relative;
text-align: center;
}
.progressbar li:before {
content: counter(step);
counter-increment: step;
width: 25px;
line-height: 25px;
display: block;
font-size: 12px;
color: transparent;
border: 6px solid #ececec;
background: #27ae60;
border-radius: 19px;
margin: 0 auto 4px;
}
.progressbar li:after {
content: '';
width: 85%;
height: 3px;
position: absolute;
left: -42%;
top: 17px;
z-index: -1;
}
.progressbar::after {
content: '';
width: 68%;
height: 3px;
background: #B9B9B9;
position: absolute;
left: 17%;
top: 17px;
z-index: -2;
}
.progressbar li:first-child:after {
content: none;
}
.progress-payment li {
width: 50%;
}
.progressbar li.active:after,
.progressbar li.active:before {
background: #27ae60;
color: white;
}
.progressbar li.half-complete:before {
color: white;
}
.progressbar li.complete:after {
background: #27ae60;
}
.progressbar li.half-complete:after {
transform: scaleX(0);
color: white;
animation: fill 3s linear forwards;
transform-origin: left;
background-color: #27ae60;
}
#keyframes fill {
to {
transform: scaleX(1);
}
}
<ul class="progressbar">
<li class="complete">Order Placed</li>
<li class="complete">Shipped</li>
<li class="active">Completed</li>
<li class="half-complete">Settled</li>
</ul>
Now using an animation-delay with a negative value:
/*progressbar*/
.progressbar {
margin-bottom: 30px;
margin-top: 10px;
counter-reset: step;
clear: both;
list-style: none;
position: relative;
}
.progressbar li {
font-size: 12px;
width: 24%;
float: left;
position: relative;
text-align: center;
}
.progressbar li:before {
content: counter(step);
counter-increment: step;
width: 25px;
line-height: 25px;
display: block;
font-size: 12px;
color: transparent;
border: 6px solid #ececec;
background: #27ae60;
border-radius: 19px;
margin: 0 auto 4px;
}
.progressbar li:after {
content: '';
width: 85%;
height: 3px;
position: absolute;
left: -42%;
top: 17px;
z-index: -1;
}
.progressbar::after {
content: '';
width: 68%;
height: 3px;
background: #B9B9B9;
position: absolute;
left: 17%;
top: 17px;
z-index: -2;
}
.progressbar li:first-child:after {
content: none;
}
.progress-payment li {
width: 50%;
}
.progressbar li.active:after,
.progressbar li.active:before {
background: #27ae60;
color: white;
}
.progressbar li.half-complete:before {
color: white;
}
.progressbar li.complete:after {
background: #27ae60;
}
.progressbar li.half-complete:after {
transform: scaleX(0);
color: white;
animation: fill 3s linear forwards;
transform-origin: left;
animation-delay: -1.5s;
background-color: #27ae60;
}
#keyframes fill {
to {
transform: scaleX(1);
}
}
<ul class="progressbar">
<li class="complete">Order Placed</li>
<li class="complete">Shipped</li>
<li class="active">Completed</li>
<li class="half-complete">Settled</li>
</ul>
Since the total duration of the animation in the demo is 3s you just use half that as a negative value to get the 50%, see how the animation starts from there.
Then we just use animation-play-state: paused; to prevent the transition.
/*progressbar*/
.progressbar {
margin-bottom: 30px;
margin-top: 10px;
counter-reset: step;
clear: both;
list-style: none;
position: relative;
}
.progressbar li {
font-size: 12px;
width: 24%;
float: left;
position: relative;
text-align: center;
}
.progressbar li:before {
content: counter(step);
counter-increment: step;
width: 25px;
line-height: 25px;
display: block;
font-size: 12px;
color: transparent;
border: 6px solid #ececec;
background: #27ae60;
border-radius: 19px;
margin: 0 auto 4px;
}
.progressbar li:after {
content: '';
width: 85%;
height: 3px;
position: absolute;
left: -42%;
top: 17px;
z-index: -1;
}
.progressbar::after {
content: '';
width: 68%;
height: 3px;
background: #B9B9B9;
position: absolute;
left: 17%;
top: 17px;
z-index: -2;
}
.progressbar li:first-child:after {
content: none;
}
.progress-payment li {
width: 50%;
}
.progressbar li.active:after,
.progressbar li.active:before {
background: #27ae60;
color: white;
}
.progressbar li.half-complete:before {
color: white;
}
.progressbar li.complete:after {
background: #27ae60;
}
.progressbar li.half-complete:after {
transform: scaleX(0);
color: white;
animation: fill 3s linear forwards;
transform-origin: left;
animation-delay: -1.5s;
animation-play-state: paused;
background-color: #27ae60;
}
#keyframes fill {
to {
transform: scaleX(1);
}
}
<ul class="progressbar">
<li class="complete">Order Placed</li>
<li class="complete">Shipped</li>
<li class="active">Completed</li>
<li class="half-complete">Settled</li>
</ul>
We can then clean it a little bit and in this demo we use some javascript to see how this can be manipulated:
.progressbar li.half-complete:after {
transform: scaleX(0);
color: white;
animation: fill 100ms linear forwards; /* Use an easier value to represent percentages in a progress bar*/
transform-origin: left;
animation-delay: inherit; /* We inherit the animation-delay from the `li` element, which we can easily manipulate with javascript*/
animation-play-state: paused;
background-color: #27ae60;
}
Final Result:
var progress = document.getElementById("progress");
var progressBarLastItem = document.querySelector(".progressbar li:last-child");
progress.addEventListener("change", function() {
progressBarLastItem.style.animationDelay = "-" + this.value + "ms";
});
/*progressbar*/
.progressbar {
margin-bottom: 30px;
margin-top: 10px;
counter-reset: step;
clear: both;
list-style: none;
position: relative;
}
.progressbar li {
font-size: 12px;
width: 24%;
float: left;
position: relative;
text-align: center;
}
.progressbar li:before {
content: counter(step);
counter-increment: step;
width: 25px;
line-height: 25px;
display: block;
font-size: 12px;
color: transparent;
border: 6px solid #ececec;
background: #27ae60;
border-radius: 19px;
margin: 0 auto 4px;
}
.progressbar li:after {
content: '';
width: 85%;
height: 3px;
position: absolute;
left: -42%;
top: 17px;
z-index: -1;
}
.progressbar::after {
content: '';
width: 68%;
height: 3px;
background: #B9B9B9;
position: absolute;
left: 17%;
top: 17px;
z-index: -2;
}
.progressbar li:first-child:after {
content: none;
}
.progress-payment li {
width: 50%;
}
.progressbar li.active:after,
.progressbar li.active:before {
background: #27ae60;
color: white;
}
.progressbar li.half-complete:before {
color: white;
}
.progressbar li.complete:after {
background: #27ae60;
}
.progressbar li.half-complete:after {
transform: scaleX(0);
color: white;
animation: fill 100ms linear forwards;
transform-origin: left;
animation-delay: inherit;
animation-play-state: paused;
background-color: #27ae60;
}
#keyframes fill {
to {
transform: scaleX(1);
}
}
<ul class="progressbar">
<li class="complete">Order Placed</li>
<li class="complete">Shipped</li>
<li class="active">Completed</li>
<li class="half-complete">Settled</li>
</ul>
<input id="progress" type="range" min="0" max="100">

Using css calc() with step

We have used a pure css base progress bar.
The main css part is as below.
.container {
width: 600px;
margin: 20px auto;
}
.progressbar {
margin: 0;
padding: 0;
counter-reset: step;
}
.progressbar li {
list-style-type: none;
width: 25%;
float: left;
font-size: 12px;
position: relative;
text-align: center;
text-transform: uppercase;
color: #7d7d7d;
}
.progressbar li:before {
width: 30px;
height: 30px;
content: counter(step);
counter-increment: step;
line-height: 30px;
border: 2px solid #7d7d7d;
display: block;
text-align: center;
margin: 0 auto 10px auto;
border-radius: 50%;
background-color: white;
}
.progressbar li:after {
width: 100%;
height: 2px;
content: '';
position: absolute;
background-color: #7d7d7d;
top: 15px;
left: -50%;
z-index: -1;
}
...............
The html
<div class="container">
<ul class="progressbar">
<li class="active">login</li>
<li>choose interest</li>
........
Complete sample could be found at https://jsfiddle.net/wbj7e79p/.
As you can see it mess up for seven step. The reason is .progressbar li width which is fixed to 25% we wanted to make it dynamic base on number of steps.
So we tried width : calc (100% / steps) or calc (100% / counter(steps)) but none of them worked. Any idea !
Please consider that we are building a component which build a progress bar on the fly, so we can not find the actual number of steps
Did you consider flexbox?
body {
font-family: 'Alegreya Sans', sans-serif;
margin: 0;
padding: 0;
}
.container {
margin: 20px auto;
}
.progressbar {
margin: 0;
padding: 0;
counter-reset: step;
display: flex;
}
.progressbar li {
list-style-type: none;
flex: 1;
font-size: 12px;
position: relative;
text-align: center;
text-transform: uppercase;
color: #7d7d7d;
}
.progressbar li:before {
width: 30px;
height: 30px;
content: counter(step);
counter-increment: step;
line-height: 30px;
border: 2px solid #7d7d7d;
display: block;
text-align: center;
margin: 0 auto 10px auto;
border-radius: 50%;
background-color: white;
}
.progressbar li:after {
width: 100%;
height: 2px;
content: '';
position: absolute;
background-color: #7d7d7d;
top: 15px;
left: -50%;
z-index: -1;
}
.progressbar li:first-child:after {
content: none;
}
.progressbar li.active {
color: green;
}
.progressbar li.active:before {
border-color: #55b776;
}
.progressbar li.active + li:after {
background-color: #55b776;
}
<h1>Four Steps</h1>
<div class="container">
<ul class="progressbar">
<li class="active">login</li>
<li>choose interest</li>
<li>add friends</li>
<li>View map</li>
</ul>
</div>
<h1> Seven Steps</h1>
<div class="container">
<ul class="progressbar">
<li class="active">login</li>
<li>choose interest</li>
<li>add friends</li>
<li>remove</li>
<li>fix users</li>
<li>review</li>
<li>save all</li>
</ul>
</div>