Skip to main content
The progress bar visualization rounds to the nearest 5% but shows the exact value next to the bars.

Fill to progress level

This style shows the unmet progress levels as unfilled, but with a border color to indicate the meaning of the level.

Setup

This chart has a very simple structure - the current measurement, the target, and the necessary calculations to create the chart. Adjust your calculation as needed for your data, but make sure you use the % formatting on the “progress” column. The following table explains each field used in the example, including the calculation formulas.
ColNameDescription or formulaPurpose
ATotal Sale PriceField measuring progress
BTarget (calc_1)Goal or target
CProgress (calc_2)=A1 / B1% of target to goal - make sure formatted as a %
DBars to fill (calc_3)=ROUND(C1 * 100 / 5, 0)Round to the number of bars to fill

Example code

<style>
ol.highlight-progress {
  --progress-padding: 3px;
  --progress-step-width: 12px;
  --progress-step-height: 56px;
  --color-bad-hsl: 343 100% 57.1%;
  --color-meh-hsl: 56 100% 57.1%;
  --color-good-hsl: 97 100% 39.6%;
  --color-bg-opacity: 0%;
  --color-border-opacity: 25%;

  list-style: none;
  margin: 0;
  padding: 0;
  background: var(--color-surface-invert);
  background: none;
  display: grid;
  grid-template-columns: repeat(20, var(--progress-step-width)) 1fr;
  gap: var(--progress-padding);
  border: calc(1.25 * var(--progress-padding)) solid var(--color-progress-bg);
  border-radius: 4px;

  & li {
    /* default is "good" */
    background: hsla(var(--color-good-hsl) / var(--color-bg-opacity));
    height: var(--progress-step-height);
    border: 1px solid hsla(var(--color-good-hsl) / var(--color-border-opacity));
  }

  & li:nth-child(-n + 13) {
    /* layer on "meh" */
    background: hsla(var(--color-meh-hsl) / var(--color-bg-opacity));
    border: 1px solid hsla(var(--color-meh-hsl) / var(--color-border-opacity));
  }

  & li:nth-child(-n + 5) {
    /* layer on "bad" */
    background: hsla(var(--color-bad-hsl) / var(--color-bg-opacity));
    border: 1px solid hsla(var(--color-bad-hsl) / var(--color-border-opacity));
  }

  & li:nth-child(-n + {{result._first.calc_3.value}}) {
    --color-bg-opacity: 50%;
  }

  & li.bar-first {
    border-radius: 4px 0 0 4px;
  }

  & li.bar-last {
    border-radius: 0 4px 4px 0;
  }

  & li.progress {
    background: transparent;
    padding-inline: 4px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    border: 0;

    & span {
      font-size: var(--font-md);
      font-weight: bold;
    }
  }
}
</style>

<ol class="highlight-progress">
  <li class="bar-first"></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li class="bar-last"></li>
  <li class="progress"><span>{{result._first.calc_2.value}}</span> to {{result._first.calc_1.value}}</li>
</ol>

Show unmet levels as faded

This style shows the unmet progress levels as solid, but semi-transparent. As the progress levels fill, they become bolder and opaque.

Setup

The data in this example shows an inverted coloring, where low is good, as it is measuring the percentage of returned or cancelled orders. You can adjust the calculations and coloring to suit your use case, but make sure you use the % formatting on the “progress” column. The following table explains each field used in the example, including the calculation formulas.
ColNameDescription or formulaPurpose
AOrder ID Count DistinctTotal number of ordersDenominator for progress calculation
BCount ReturnedNumber orders returnedPart of the numerator for progress calculation
CCount CancelledNumber orders cancelledOther part of the numerator for progress calculation
DReturn and Cancel Rate (calc_1)=(B1 + C1) / A1% calculation for number returned or cancelled
EBars to fill (calc_2)=ROUND(D1 * 100 / 5, 0)Round to the number of bars to fill

Example code

<style>
ol.highlight-progress {
  --progress-padding: 3px;
  --progress-step-width: 12px;
  --progress-step-height: 56px;
  --color-bad-hsl: 343 100% 57.1%;
  --color-meh-hsl: 56 100% 57.1%;
  --color-good-hsl: 97 100% 39.6%;
  --color-bg-opacity: 15%;

  list-style: none;
  margin: 0;
  padding: 0;
  background: var(--color-surface-invert);
  background: none;
  display: grid;
  grid-template-columns: repeat(20, var(--progress-step-width)) 1fr;
  gap: var(--progress-padding);
  border: calc(1.25 * var(--progress-padding)) solid var(--color-progress-bg);
  border-radius: 4px;

  & li {
    /* default is "bad" */
    background: hsla(var(--color-bad-hsl) / var(--color-bg-opacity));
    height: var(--progress-step-height);
  }

  & li:nth-child(-n + 10) {
    /* layer on "meh" */
    background: hsla(var(--color-meh-hsl) / var(--color-bg-opacity));
  }

  & li:nth-child(-n + 3) {
    /* layer on "good" */
    background: hsla(var(--color-good-hsl) / var(--color-bg-opacity));
  }

  & li:nth-child(-n + {{result._first.calc_2.value}}) {
    --color-bg-opacity: 100%;
  }

  & li.progress {
    background: transparent;
    padding-inline: 4px;
    display: flex;
    flex-direction: column;
    justify-content: center;

    & span {
      font-size: var(--font-md);
      font-weight: bold;
    }
  }
}
</style>

<ol class="highlight-progress">
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li class="progress"><span>{{result._first.calc_1.value}}</span>of orders cancelled or returned</li>
</ol>