Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simple bar progress indicator static or animated

I need to make a simple bar progress indicator - actually I just need a bar with a green portion for the good amount and another coloured portion for the bad amount and the percent good somewhere in the middle of the bar. Assume the bar is 50px wide and 15px high. Think static progress bar like example below.

enter image description here

I have done this before using jquery and a background div with 2 further divs positioned on top of it for the good and bad indicators, then a positioned div above that to display the text.

However I am wondering if there is a much more simple HTML5 canvas, SVG or CSS solution. As this timy control will appear in every row of a long table, the aim is to pollute the DOM less and make greater readability and re-usability.

I know there are libraries that do this but I wanted to use it as a learning experience. The solution should be either no script, or JS only, or JS with jquery.

EDIT: Thanks for the positive input folks. I propose my own solution with working snippet in the answers below as I think it is worthy of standing alone for votes etc. No-one has proposed an SVG solution yet - any takers?

Image of my propsal:

enter image description here

EDIT 2: 3 excellent solutions (plus mine) so far. Has turned out to be quite an interesting weekend challenge. Any more ?

EDIT - ANSWER SELECTED: In the interests of closure, I have selected and answer to award the points. However, all of the proposed answers seem viable in different situations. For my purposes the SVG-based answer from Mr Le Beau was the optimum. My parameters for selection were that I initially make the page markup on the server and can therefore set all the values necessary to render the bars without code execution. Later I allow a change to the percent complete which I accomplish with an ajax post to the server and simple jquery to update the text and bar coverage.

I would hope that in time the HTML5 progress tag answer will make this question redundant, but then again we might all be sitting on the deck at the developers rest home sipping cocktails by then (maybe).

Thank you all for your efforts.

like image 540
Vanquished Wombat Avatar asked May 28 '26 16:05

Vanquished Wombat


2 Answers

Here's an SVG equivalent of your offering.

$("svg.tbc").each(function(i, item) {
  var $item = $(item);
  var rate = $item.parent().find(".country").attr("rate");
  $item.find(".bar").attr("width", rate);
  $item.find("text").text(rate);
});
.tbc {
  width: 50px;
  height: 15px;
}

.tbc .bg {
  fill: gold;  
  fill-opacity: 0.5;
}

.tbc .bar {
  fill: blue;
  fill-opacity: 0.5;
}

.tbc text {
  font-size: 8pt;
  font-family: Calibri, sans-serif;
  font-weight: bold;
  fill: blue;
}

.country {
  display: inline-block;
  width: 200px;
}

.info {
  margin-top: 20;
  font-size: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1>Urban population rate by country </h1>

<div>
  <div class="country" rate="57.6%">China</div>
  <svg class="tbc"><rect class="bg" width="100%" height="100%"/><rect class="bar" width="0%" height="100%"/><text x="50%" y="70%" text-anchor="middle">0%</text></svg>
</div>

<div>
  <div class="country" rate="32%">India</div>
  <svg class="tbc"><rect class="bg" width="100%" height="100%"/><rect class="bar" width="0%" height="100%"/><text x="50%" y="70%" text-anchor="middle">0%</text></svg>
</div>

<div>
  <div class="country" rate="82.1%">U.S.</div>
  <svg class="tbc"><rect class="bg" width="100%" height="100%"/><rect class="bar" width="0%" height="100%"/><text x="50%" y="70%" text-anchor="middle">0%</text></svg>
</div>

<div>
  <div class="country" rate="73.2%">Russia</div>
  <svg class="tbc"><rect class="bg" width="100%" height="100%"/><rect class="bar" width="0%" height="100%"/><text x="50%" y="70%" text-anchor="middle">0%</text></svg>
</div>

<div>
  <div class="country" rate="81.2%">UK</div>
  <svg class="tbc"><rect class="bg" width="100%" height="100%"/><rect class="bar" width="0%" height="100%"/><text x="50%" y="70%" text-anchor="middle">0%</text></svg>
</div>

<div>
  <div class="country" rate="11.5%">Burundi</div>
  <svg class="tbc"><rect class="bg" width="100%" height="100%"/><rect class="bar" width="0%" height="100%"/><text x="50%" y="70%" text-anchor="middle">0%</text></svg>
</div>

<div class="info"><a href="http://www.worldometers.info/world-population/population-by-country/" target="">Source: www.worldometers.info/</a>
like image 181
Paul LeBeau Avatar answered May 31 '26 07:05

Paul LeBeau


You could do it with just one DIV and the pseudos :before and :after, one for background and one for the text, like here https://jsfiddle.net/3keey3t6/2/

.progress::before {
    position: absolute;
    top: 0;
    left: 0;
    width: 100px;
    bottom: 0;
    background: #eee;
    content: "";
    z-index: -1;
}

.progress {
    position:relative;
    width:75px;
    height:35px;
    background:green;
}

.progress:after {
    position: absolute;
    content: attr(data-progress) '%';
    width: 100%;
    line-height: 35px;
    text-align: center;
    color: white;
    text-shadow:1px 0 0 black, 0 1px 0 black, -1px 0 0 black, 0 -1px 0 black;
}

and then

<div id="pbar" class="progress" data-progress="20"/>

and

function setProgress(p) {
    var prg = document.getElementById("pbar");
    prg.style.width = p+"px";
    prg.setAttribute("data-progress", p);
}

setProgress(10);

Just a very simple example if the goal is to pollute DOM as less as possible ...

like image 35
rupps Avatar answered May 31 '26 06:05

rupps



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!