user6655274
user6655274

Reputation:

How to display data label inside HTML5 progress bar? (cross-browser)

I have a styled HTML5 progress bar for which I would like to show the data label inside the progress bar cross-browser compatible. Currently it is displayed above the progress bar.

HTML:

<progress max="100" value="50" data-label="50% Complete"></progress>

CSS:

progress {
  text-align:center;
  height: 1.5em;
  width: 100%;
  -webkit-appearance: none;
  border: none;
}
progress:before {
  content: attr(data-label);
  font-size: 0.8em;
  vertical-align: 0
}
progress::-webkit-progress-bar {
  background-color: #c9c9c9;
}
progress::-webkit-progress-value,
progress::-moz-progress-bar {
  background-color: #7cc4ff;
}

I'm getting the result below, but I'd like to move the data label inside the progress bar:

current rendering

Upvotes: 32

Views: 41773

Answers (3)

Sergey Anisimov
Sergey Anisimov

Reputation: 371

Apparently I needed to make CSS HTML progressbar with centered text and found this answer, but answers here don't have centered text. Here is HTML , CSS progress bar with centered text.

#progress_container {
  width: 100px;
  background-color: rgb(161, 161, 161);;
  height: 30px;
  position: relative;
}

#progress_container_text {
  position: absolute;
  left: 0;
  right: 0;
  height: 100%;
}

#progress_container_text_align_center {
  display: flex;
  height: 100%;
  justify-content: center;
  align-items: center;
}

#loading_bar {
  width: 30%;
  height: 100%;
  background-color: rgb(58, 166, 255);
}
<div id="progress_container">
  <div id="progress_container_text">
    <div id="progress_container_text_align_center">30%</div>
  </div>
  <div id="loading_bar"></div>
</div>

Upvotes: 1

John
John

Reputation: 13757

All you need to do is set the status text to have a z-index of 1 (-1 is invalid, 0 is the default) on the status text element and then set a negative margin-top: -32px (for a height: 32px) and you can keep the progress element without adding any excess:

<div style="z-index: 2;"><span>Staging item 144 of 271...</span></div>
<div style="margin-top: -32px;"><progress max="100" value="44">44%</progress></div>

Upvotes: 1

Jacob G
Jacob G

Reputation: 14172

TL;DR: Don't use pseudo elements on a <progress> element.

As said in other answers, and by me in the comments, a HTML/CSS progress bar would be a better solution than using the <progress> element.

Gecko-based browsers, like firefox, won't display the pseudo element at all.

However, to answer your question, just position the text over the progress bar:

progress {
  text-align: center;
  height: 1.5em;
  width: 100%;
  -webkit-appearance: none;
  border: none;
  
  /* Set the progressbar to relative */
  position:relative;
}
progress:before {
  content: attr(data-label);
  font-size: 0.8em;
  vertical-align: 0;
  
  /*Position text over the progress bar */
  position:absolute;
  left:0;
  right:0;
}
progress::-webkit-progress-bar {
  background-color: #c9c9c9;
}
progress::-webkit-progress-value {
  background-color: #7cc4ff;
}
progress::-moz-progress-bar {
  background-color: #7cc4ff;
}
<progress max="100" value="50" data-label="50% Complete"></progress>

Note that this does not have good browser support(In fact, it's pretty horrible), because <progress> is a replaced element, like <input>.

The CSS specs are not completely clear on if replaced elements can have pseudo elements, so different browsers have different renderings. Webkit-based browsers, such as Chrome, will sometimes display them. Gecko-based, such as Firefox, will not.

See this answer on a somewhat similar question.

So, if this is for a website, and not a electron app or similar, I highly recommend using a HTML/CSS Progress bar:

.progress {
  height: 1.5em;
  width: 100%;
  background-color: #c9c9c9;
  position: relative;
}
.progress:before {
  content: attr(data-label);
  font-size: 0.8em;
  position: absolute;
  text-align: center;
  top: 5px;
  left: 0;
  right: 0;
}
.progress .value {
  background-color: #7cc4ff;
  display: inline-block;
  height: 100%;
}
<div class="progress" data-label="50% Complete">
  <span class="value" style="width:50%;"></span>
</div>

Note: Even if this is for an application with a webkit-based browser, you still shouldn't use psuedo elements on a <progress>. As I said above, the specs for this functionality are unclear, which could change in the future, breaking your progress element. Webkit could also drop support for this.

I would recommend just using a HTML/CSS progress bar, you'll save yourself a lot of trouble in the future.

Upvotes: 45

Related Questions