Even Better Inline Progress Bars

In the handful of months since I last posted about inline progress bars, I've made some enhancements to the mechanism. In particular, the original mechanism didn't handle overages very gracefully, and while overage isn't strictly needed for progress, I've ended up wanting the same inline display for other types of measurements (e.g., fundraising dollars against a goal).

The JS has grown slightly more complicated, creating a richer structure to style to handle some of the new stuff:

jQuery(".progress").each(function() {
  var $this = jQuery(this)
  var frac = parseFloat($this.attr("rel"))
  if (isNaN(frac)) {
    return // bad data
  }
  var html = $this.html();
  $this.empty()
    .append(''
      + '<span class="container">'
        + '<span class="status-text-spacer">' + html + '</span>'
        + '<span class="progress-bar" style="width:' + (frac * 100) + '%;"></span>'
        + '<span class="status-text" style="width:' + Math.max(100, frac * 100) + '%;">'
          + '<span class="status-text-spacer">' + html + '</span>'
        + '</span>'
      + '</span>'
    )
  if (frac >= 1) {
    $this.addClass("overage") // strictly for external targetting
      .find(".container")
        .css({
          marginRight: (100 - 100 / frac) + "%",
          width: (100 / frac) + "%"
        })
  }
})

The CSS is still about the same for the base functionality, but with the new stuff, it's far richer:

.progress {
  display: inline-block;
  position: relative;
}
.progress .container {
  display: inline-block;
  position: relative;
  border: 1px solid #999;
  background-color: #f7f7f7;
  color: #f7f7f7;
  white-space: nowrap;
  padding: 0;
  margin: 0;
  width: 100%;
}
.progress .container .progress-bar {
  display: inline-block;
  position: absolute;
  z-index: 0;
  top: 0;
  left: 0;
  height: 100%;
  filter: alpha(opacity=80); /* yeah IE! */
  opacity: 0.8;
  /* .neutral is the default */
  background-color: #ddd;
  border-right: 1px solid #666;
}
.progress.overage.neutral-overage .container .progress-bar {
  background-color: #ddd;
  border-right: 1px solid #666;
}
.progress.ok .container .progress-bar,
.progress.overage.ok-overage .container .progress-bar {
  background-color: #dfd;
  border-right: 1px solid #393;
}
.progress.error .container .progress-bar,
.progress.overage.error-overage .container .progress-bar {
  background-color: #fdd;
  border-right-color: #c66;
}
.progress .container .status-text {
  display: inline-block;
  position: absolute;
  z-index: 1;
  top: 0;
  left: 0;
  color: #000;
  margin: 0;
  padding: 0;
}
.progress .container .status-text-spacer {
  margin: 0 5px;
}

So now instead of just doing this (which will render a neutral bar):

<span class="progress" rel="#raised / goal#">
  #dollarFormat(raised)# of #dollarFormat(goal)# raised...
</span>

You can control the various presentation very granularly (red below 100% and green from 100% up):

<span class="progress error ok-overage" rel="#raised / goal#">
  #dollarFormat(raised)# of #dollarFormat(goal)# raised...
</span>

The original version rendered green bars for everything, with this incarnation you can have neutral, ok, or error semantics for your bars.

One response to “Even Better Inline Progress Bars”

  1. Henry Ho

    Wonder when we can use Progress tag in html5 with polyfill backward compatibility…