'Make bar/progress chart with JS and CSS [closed]

If I have data like displayed on top of the image. Is it posible to make a diagran like this (picture), with pure JS, CSS and HTML? I dont know what a diagram/chart like this is called. Any help is greatly appreciated!

enter image description here



Solution 1:[1]

The most straightforward approach is to use an absolutely positioned child in a relatively positioned parent and set its width as the progress.

function setProgress(percent) {
  const range = document.querySelector('.range');
  const progress = range.querySelector('.progress');
  
  progress.style.width = `${percent}%`
}

setProgress(70);
.range {
  position: relative;
  height: 20px;
  background-color: #ed3a23;
  border: 2px solid #000;
  box-sizing: border-box;
  overflow: hidden;
}

.progress {
  position: absolute;
  left: 0;
  top: 0;
  width: 0;
  height: 100%;
  background-color: #4db24c;
  border-right: 3px solid #000;
}
<div class="range">
  <div class="progress"></div>
</div>

Solution 2:[2]

You don't need JavaScript.
Pass a CSS var() from HTML to CSS and use calc() to get the percentages

Using background linear gradient

.progress {
  background: green;
  height: 2em;
  background: linear-gradient(to right, green calc(var(--val) * 10%), red calc(var(--val) * 10%));
  background-size: 100%;
}
<div class="progress" style="--val:1"></div><br>
<div class="progress" style="--val:7"></div><br>

Using CSS pseudo element ::before

.progress {
  background: red;
  height: 2em;
}
.progress::before {
  content: "";
  display: block;
  height: inherit;
  background: green;
  width: calc(var(--val) * 10%);
}
<div class="progress" style="--val:1"></div><br>
<div class="progress" style="--val:7"></div><br>

Solution 3:[3]

Here's pure HTML & CSS

.bar-wrap {
  display: flex
}
.col {
  display: block;
  text-align:center;
  width: var(--size)
}
.bar {
  height: 50px;
  width: 100%;
  border: 3px solid #000;
  background: var(--background)
}
.cgreen {
  color: green
}
.cred {
  color: red
}
<div class="bar-wrap">
  <div class="col cgreen" style="--size:70%;">
    <h3 class="heading">Correct</h3>
    <div class="bar" style="--background:green"></div>
    <p class="label">70%</p>
  </div>
  <div class="col cred" style="--size:30%;">
    <h3 class="heading">Wrong</h3>
    <div class="bar" style="--background:red"></div>
    <p class="label">30%</p>
  </div>
</div>

Solution 4:[4]

To meet accessibility and semantic code standards, I'd recommend having a look into the HTML <meter> element (official specification with all the attributes). Or you just have a look on HTML5 doctor to get a more compact/short conclusion.

However, keep in mind that according to caniuse.com, legacy browsers like Edge 12 and others don't support this HTML tag. So if you want to support these older browsers, that are listed there as non-supporting, you would need to come up with a fallback solution.

Rough code example for a fallback solution

<div class="meter-wrapper">
  <div class="meter" style="width: 70%;">
    <!-- `hidden` attribute to hide the text content but keeping the element accessible for screen readers. -->
    <p class="meter__text-fallback meter__text-fallback--correct"><strong>70%</strong><span hidden>of given answers are correct.</span></p>
  </div>
  <p class="meter__text-fallback meter__text-fallback--incorrect"><strong>30%</strong><span hidden>of given answers are incorrect.</span></p>
</div>

and style it something like this:

/* CSS */
.meter-wrapper {
  background-color: pink;
  height: 40px;
  position: relative;
}

.meter {
  display: inline-block;
  background-color: MediumAquamarine;
  height: 100%;
  position: relative;
}

.meter__text-fallback {
  position: absolute;
  margin: 0;
  bottom: -25px;
}

/* This class block is not utterly necessary, since the default value for `left` is already `0`. Just in case you want to have different values. */
.meter__text-fallback--correct {
  left: 0;
}

.meter__text-fallback--incorrect {
  right: 0;
}

See this code example in action

Link to codepen

Important notes to this code example

  1. I would recommend to change your layout from having the percentage of correct and incorrect answers outside the meter bars to avoid a case, where you would have a slimmer bar than the width of the typography overlapping it.

  2. Setting the values for the style="width: 70%" attributes would need to be controlled via JS. It is also arguable to style HTML elements with inline styles, like I did in this example. On the other hand creating a 100+ different CSS classes for such a case, might be overkill. Styling via data attributes is also not fully supported. So I'll leave this decision up to you.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 pouria
Solution 2
Solution 3
Solution 4 Kayzah