Showing a generated content before element on a progress bar using the ::before pseudo-class

I'm currently attempting to showcase a ::before pseudo-element on a <progress> bar in the form of a label featuring the value attribute. My current approach successfully displays the ::before element in Brave (v1.61.109), but unfortunately, it does not show up in Safari(17.1.2) and Firefox (121.0). Despite this, I am facing a challenge related to the height of the pseudo-element. It seems that the pseudo-element itself does not directly impact the layout flow. Nevertheless, I am eager to discover an effective workaround.

Moreover, besides just displaying the element, I aim for it to be factored into the height calculation of the parent box, specifically within the context of .card. I am seeking a solution that adapts dynamically.

https://i.sstatic.net/7vjSf.jpg

Below is the provided HTML code:

<div class="card">
    <p>Item 1</p>
    <p>Item 2</p>
    <progress max="100" value="100"></progress>
</div>

Additionally, here is the corresponding CSS:

.card {
    display: flex;
    flex-direction: column;
    width: 300px;
    background: beige;
}

progress[value] {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    border: none;
    width: 100%;
}

progress {
    position: relative;
}

progress:before {
    content: attr(value) '% some text here';
    font-size: 2rem;
    color: black;
    text-align: center;
    height: 2rem;
    line-height: normal;
}

progress[value]::-webkit-progress-value {
    background-color: green;
    border-radius: .2rem;
}

progress[value]::-moz-progress-bar {
    background-color: green;
    border-radius: .2rem;
}

If anyone has suggestions on how to address this visualization issue, please share your ideas!

Answer №1

While considering your query, I stumbled upon a potential solution involving the use of JavaScript to update the progress percentage instead of utilizing CSS's attr() function.

There are two key reasons for opting for JavaScript in this scenario:

  1. It offers simplicity in implementation.
  2. By using JavaScript, we can avoid certain issues associated with the :before pseudo-element, particularly its compatibility concerns with Safari and size calculation within the parent element.

In this approach, employing a

<div id="progress-label"></div>
allows us to confine the progress percentage display within the parent (.card) element, leveraging its block-level nature and static positioning. The JavaScript code merely updates the text content within this div element dynamically during execution.

You may experiment with this template and customize it to suit your requirements. Feel free to explore a live demonstration on CodePen via the following link: https://codepen.io/Jun-Wen-Soh/pen/ZEPQgGR

HTML

<div class="card">
  <p>Item 1</p>
  <p>Item 2</p>
  <div class="wrapper">
    <div id="progress-label"></div>
    <label for="progress-bar">Progress:</label>
    <progress id="progress-bar" max="100" value="100"></progress>
  </div>
</div>

CSS

.card {
  display: flex;
  flex-direction: column;
  width: 300px;
  background: beige;
  padding: 15px;
}

.wrapper {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

progress[value] {
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  border: none;
  width: 100%;
}

progress {
  position: relative;
}

#progress-label {
  font-size: 2rem;
  color: black;
  text-align: left;
  height: 2rem;
  line-height: normal;
}

progress[value]::-webkit-progress-value {
  background-color: green;
  border-radius: .2rem;
}

progress[value]::-moz-progress-bar {
  background-color: green;
  border-radius: .2rem;
}

JS

const progressBar = document.getElementById('progress-bar');
const progressLabel = document.getElementById('progress-label');

progressLabel.textContent = progressBar.value + '% some text here';

Answer №2

Concerns Surrounding Pseudo-elements in CSS

  1. The before pseudo-element is positioned prior to the content inside the tag, rather than preceding the opening of the tag itself. Consequently, the flex rule fails to apply correctly since it targets the direct children of .car, while the :befoer pseudo-element is the initial child of <progress>.
  2. Furthermore, as indicated in the documentation here, using a pseudo-element on an HTML element that is not part of the document tree is not supported.
  3. In addition, content generated via CSS remains inaccessible to screen readers, thus underscoring the importance of ensuring that CSS-generated content does not hinder page comprehension.

To address these issues, adjustments to the HTML code are necessary:

<div class="card">
    <p>Item 1</p>
    <p>Item 2</p>
    <label for="progress">% some text here</label>
    <progress id="progress" max="100" value="100">toto</progress>
</div>

An inclusion of JavaScript similar to the snippet below may be beneficial:

const progressElement = document.getElementById('progress');
const progressLabelElement = document.querySelector('[for=progress]');
const initialTextContent = progressLabelElement.textContent;

function updateValue() {
    progressLabelElement.textContent = progressElement.value + initialTextContent;
}
// this is not needed if the value does not change
progressElement.addEventListener('input', updateValue);

updateValue()

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Navigate to the following section on an HTML page by clicking a button using jQuery

Within my application using Jquery / Javascript, I am looking to implement a specific functionality. I currently have several div elements like the ones below: <div id="div1"></div> <div id="div2"></div> <div id="div3"></ ...

The behavior of CSS position: sticky varies depending on whether the user is scrolling up or scrolling down

I am experiencing an issue in my Vue CLI app where a component with the position: sticky CSS property is being partially hidden under the top of the browser when scrolling down, but works correctly when scrolling up. This behavior is also observed on my Ga ...

Using a single name in the form, input multiple parameters and retrieve a comprehensive list of all of them

I'm struggling with a form that has dynamic fields. After submitting the form, I am getting this URL: Localhost:8000/mysite.com/jobs_form?job="Job1"&job="Job2" But I am unable to retrieve all of them in Django using reques ...

HyperText Markup Language, Cascading Style Sheets, and JavaScript

In my div, I have a combination of icons and text. I'm trying to center only the text within the div, with two icons on the left and 4 to 5 icons on the right. Although I managed to position the icons correctly, I am having trouble aligning the text ...

The CSS border on a div has inexplicably ceased functioning in Chrome, yet continues to work perfectly in

Just a moment ago, something strange happened while I was working on my memory game. After reopening the page, the borders around the divs stopped showing up when navigating with the keyboard arrows. (Click in the window to activate the arrow keys.) Normal ...

Tips for optimizing Slider Code to showcase an expanded selection of slides

I am currently troubleshooting a slider code on my ASP.NET website. After examining the HTML, JS, and CSS from the page theme, I noticed that only two slides are being displayed. However, when attempting to add a new slider HTML and adjusting the CSS for t ...

What is the best way to click on a specific webElement in a group of webElements using Python Selenium?

After discovering how to locate a subelement of an element using Selenium in python through this informative Stack Overflow post, I am now eager to take my skills to the next level. Selenium Get WebElement inside a WebElement My goal is to be able to exe ...

Angular components are not receiving the Tailwind CSS attributes applied to :root classes

In my Angular 12 project, I have integrated Tailwind CSS. The structure of the package.json is as below: { "name": "some-angular-app", "version": "0.0.0", "scripts": { "ng": "ng&quo ...

What is the best way to include a permanent placeholder within an input field?

I'm trying to insert a font icon inside an input field using the following method: <input type="text" name="your name" placeholder="&#xe00b; YOUR NAME" style="font-family:Flaticon" class="restrict"> Currently, the font icon &#xe00b; is ...

Eliminate the bottom padding on the body in your HTML and CSS code

My Unique Code <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8> <style> /*RESET BLOCK START ------------------------------------------------------------------------------------------------------------------*/ ...

Animating divs one by one using CSS3 with delays

I am experimenting with animating three separate divs one by one, each moving down 50px as a test. Here is the SCSS code I am using: .action { margin: 20px 0; text-align: center; transform: translate(0,0); transition: ...

What is the best way to incorporate the .top offset into a div's height calculation?

Looking to enhance the aesthetic of this blog by adjusting the height of the #content div to match that of the last article. This will allow the background image to repeat seamlessly along the vertical axis. I attempted the following code: $(document).re ...

What is the best way to include content within the li element?

I'm trying to figure out how to insert a block inside an li element in HTML. Here's what I have: <ul> <li> <button onclick="expand()">+</button> Parent 1 </li> </ul> This is what I want ...

Working with HTML5 canvas to draw multiple images

Here is the code I'm working with: http://jsfiddle.net/zyR9K/4/ var Enemies = { x: 25, y: 25, width: 20, height: 30, speed: 0.5, color: "#000", draw: function () { canvas.fillStyle = ...

Having trouble displaying data from a MongoDB database using ng-repeat in AngularJS

Currently, I am facing an issue while trying to retrieve data from the database and display it using ng-repeat. The getAll function in the factory is fetching the data properly, returning an object with all the information. However, when I try to display t ...

Concealing a message within a section that has been minimized to a width of 0

Recently, I've encountered a challenge in attempting to set the width of a section to 0 and have all its contents also disappear. Despite changing the section's width to 0px, the text inside continues to be displayed and even shifts off to the si ...

Using Tailwind CSS's width property w-11/12 actually returns a full 100% width instead of the expected 91.66

It seems that the w-11/12 class is not behaving as expected. According to the documentation, it should give a width of 91.666% but instead, it's filling up 100%. This issue only occurs with the value 11, while other values work fine. Has anyone else e ...

Error: The EJS compiler encountered a SyntaxError due to an unexpected token || in the show component file located at /var/www/html

I'm currently working on a project inspired by Colt Steele's YelpCamp creation during his Udemy Web Dev Bootcamp. Everything was going smoothly until I tried to refactor some code towards the end of the course using YouTube tutorials. Now, whenev ...

Alternative background for browsers that do not have support for border-image styling

I am experimenting with CSS3 border-image to create a simple button design: the left slice of the image is intended to be the left border of the text, the right slice as the right border, and the middle slice should either repeat or stretch as a background ...

Achieving the perfect overlay and centered image effect using CSS

I am attempting to design a banner consisting of 3 images, each with dimensions of 900x420, similar to the image shown below. I am looking for advice on how to align these images such that they are horizontally centered. Any suggestions would be greatly ap ...