2

I have an indeterminate progress bar:

<progress max="100"></progress>

I've styled it with a green background with 45-degree stripes:

progress {
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  border: none;
}

progress:not([value])::-webkit-progress-bar {
  background-image:
    -webkit-linear-gradient(-45deg, transparent 33%, rgba(0, 0, 0, 0.2) 33%, rgba(0, 0, 0, 0.2) 66%, transparent 66%),
    -webkit-linear-gradient(#b3ee3a, #b3ee3a);
  background-size: 2.5em 1.25em, 100% 100%, 100% 100%;
  background-position: 10%;
  animation-name: stripes;
  animation-duration: 2s;
  animation-iteration-count: infinite;
}

@keyframes stripes {
  from {background-position: 0%}
  to {background-position: 100%}
}

(Full Example: https://jsfiddle.net/w9x7sm6c/4/)

Unfortunately, the animation doesn't work. The issue seems to stem from a Chrome bug/feature:

https://bugs.chromium.org/p/chromium/issues/detail?id=486195

Closing this as WontFix.

Reason: @keyframes rule name is scoped, so the name specified is only available in the same treescope (i.e. in the same document or shadow root). progress::-webkit-progress-value pierces document-UA shadow root boundary and styles the element, but animation name defined in the document treescope isn't available in UA shadow root, thus the animation doesn't apply.

...

A workaround could be to make your own widget and animate it, which should work all (if CSS animation is implemented) browsers.

It seems to me that the suggested workaround is to just not use <progress>, which seems like bad advice to me. I'd rather use the correct semantic elements than inventing something that does the same thing.

Is there any workaround I can use for animating this progress bar in its indeterminate state?

Hien Nguyen
  • 24,551
  • 7
  • 52
  • 62
Brad
  • 159,648
  • 54
  • 349
  • 530
  • some JS to simulate the animation maybe? – Temani Afif Apr 29 '19 at 15:35
  • @TemaniAfif Thanks, I was just trying that out! Unfortunately, there doesn't seem to be any way to select `progress:not([value])::-webkit-progress-bar` in JavaScript. `document.querySelector()` for it returns `null`. – Brad Apr 29 '19 at 15:36
  • yes you will need CSS variable (ex: https://stackoverflow.com/a/54749459/8620333) – Temani Afif Apr 29 '19 at 15:38

1 Answers1

2

You can consider the common pseudo element to create this.

body {
  background: #333;
}

progress {
  display: block;
  margin-bottom: 1em;
  position:relative;
}

progress {
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  border: none;
}

progress::-webkit-progress-bar {
  background-color: #777;
  border-radius: 0.3em;  
}

progress[value]::-webkit-progress-bar {
  box-shadow: 0 0.3em 0.3em rgba(0,0,0, 0.3) inset;
}

progress::-webkit-progress-value {
  border-radius: 0.3em;
  background-color: #b3ee3a;
}


progress:not([value])::-webkit-progress-bar {
  /* nothing here*/
}
progress:not([value])::before {
  content:"";
  position:absolute;
  top:0;
  left:0;
  right:0;
  bottom:0;
  border-radius: 0.3em; 
  background:
    linear-gradient(-45deg, transparent 33%, rgba(0, 0, 0, 0.2) 33%, rgba(0, 0, 0, 0.2) 66%, transparent 66%) left/2.5em 1.25em,
    #b3ee3a;
  background-position: 10%;
  animation-name: stripes;
  animation-duration: 2s;
  animation-iteration-count: infinite;
}

@keyframes stripes {
  from {background-position: 0%}
  to {background-position: 100%}
}
<progress max="100" value="33"></progress>
<progress max="100" value="50"></progress>
<progress max="100" value="90"></progress>
<progress max="100"></progress>

Or use JS to update the values using CSS variables combined with timeout.

Here is a basic example to show the value change:

function update() {
  document.querySelector('progress:not([value])').style.setProperty("--c", "100%");
}
progress {
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  border: none;
}

progress:not([value])::-webkit-progress-bar {
  background:
    linear-gradient(-45deg, transparent 33%, rgba(0, 0, 0, 0.2) 33%, rgba(0, 0, 0, 0.2) 66%, transparent 66%),
    #b3ee3a;
  background-size: 2.5em 1.25em;
  background-position: var(--c,10%);
  transition:1s all;
}
<progress max="100"></progress>

<button onClick="update()">change</button>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415