I'm trying to animate the progress bar (HTML5 <progess>
tag). I managed to style the Shadow DOM elements, but I can't animate the background (repeating linear gradient). It works in Firefox, but not in Chrome and Edge.
<ins>
By it does not work I mean, the striped background is shown, but it is not animated</ins>
It seems as if the @keyframe
animation definition has a different scope outside of the shadow boundary.
<ins>
How can I break the scope of the Shadow DOM boundary?
Or is there a way that I can override the User Agents shadow DOM implementation?
</ins>
<ins>
I would be glad, if there is a No-JS solution
</ins>
.progress {
position: relative;
}
.progress::before {
content: attr(title);
position: absolute;
z-index: 100;
width: 100%;
height: 100%;
display: -webkit-box;
display: flex;
-webkit-box-align: center;
align-items: center;
-webkit-box-pack: center;
justify-content: center;
text-align: center;
font-size: 2rem;
font-weight: 700;
line-height: 1.4;
}
progress[value] {
display: block;
width: 100%;
min-height: 4rem;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
border: none;
border-radius: 10px;
box-shadow: inset 4px 4px 4px rgba(84, 30, 8, 0.2);
background-color: rgba(149, 250, 61, 0.1);
border: 1px solid #ccc;
}
progress[value]::-webkit-progress-inner-element {
border-radius: 10px;
overflow: hidden;
}
progress[value]::-webkit-progress-bar {
border-radius: 10px;
/* box-shadow: inset 4px 4px 4px rgba(84, 30, 8, 0.2); */
background-color: transparent;
}
progress[value]::-webkit-progress-value {
border-radius: 10px 0 0 10px / 10px 0 0 10px;
box-shadow: inset 2px 2px 2px rgba(84, 30, 8, 0.2);
background-color: #95fa3c;
position: relative;
background-image: repeating-linear-gradient(45deg, transparent 0, transparent 6px, rgba(0, 0, 0, 0.1) 6px, rgba(0, 0, 0, 0.1) 12px);
background-size-x: 800942px; /* empirical value */
-webkit-animation: colorrush 3s infinite linear;
animation: colorrush 3s infinite linear;
}
progress[value]::-moz-progress-bar {
border-radius: 10px 0 0 10px / 10px 0 0 10px;
box-shadow: inset 2px 2px 2px rgba(84, 30, 8, 0.2);
background-color: #95fa3c;
position: relative;
background-image: repeating-linear-gradient(45deg, transparent 0, transparent 6px, rgba(0, 0, 0, 0.1) 6px, rgba(0, 0, 0, 0.1) 12px);
background-size: 800942px; /* empirical value */
animation: colorrush 3s infinite linear;
}
@-webkit-keyframes colorrush {
0% {
background-color: #95fa3c;
background-position-x: 0;
}
50% {
background-color: #c4eea0;
}
100% {
background-color: #95fa3c;
background-position-x: 152px; /* empirical value */
}
}
@keyframes colorrush {
0% {
background-color: #95fa3c;
background-position-x: 0;
}
50% {
background-color: #c4eea0;
}
100% {
background-color: #95fa3c;
background-position-x: 152px; /* empirical value */
}
}
html {
font-size: 62.5%;
font-family: sans-serif;
}
body {
font-size: 1.6rem;
}
<div class="progress" title="125 / 150 (83.33%)">
<progress max="150" value="125">125 / 150</progress>
</div>
Inheritance can fix the issue. You apply the animation on the main element and you use a cascading inherit
. Since it won't work with background-color
I replaced the animation with a gradient one where I will also animation the position.
I also optimized the code to avoid the empircal value
progress[value] {
display: block;
width: 100%;
min-height: 4rem;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
border: none;
border-radius: 10px;
box-shadow: inset 4px 4px 4px rgba(84, 30, 8, 0.2);
background-color:rgba(149, 250, 61, 0.1);
border: 1px solid #ccc;
animation: colorrush 5s infinite linear;
}
progress[value]::-webkit-progress-inner-element {
border-radius: 10px;
overflow: hidden;
background-position:inherit;
}
progress[value]::-webkit-progress-bar {
border-radius: 10px;
background-color: transparent;
background-position:inherit;
}
progress[value]::-webkit-progress-value {
border-radius: 10px 0 0 10px / 10px 0 0 10px;
box-shadow: inset 2px 2px 2px rgba(84, 30, 8, 0.2);
background:
repeating-linear-gradient(45deg, transparent 0 6px, rgba(0, 0, 0, 0.1) 6px 12px),
linear-gradient(#95fa3c,#c4eea0,#95fa3c);
background-size:
calc(12px/0.707) 100%, /* 0.707 = cos(45deg)*/
100% 800%;
background-position:inherit;
}
progress[value]::-moz-progress-bar {
border-radius: 10px 0 0 10px / 10px 0 0 10px;
box-shadow: inset 2px 2px 2px rgba(84, 30, 8, 0.2);
background:
repeating-linear-gradient(45deg, transparent 0 6px, rgba(0, 0, 0, 0.1) 6px 12px),
linear-gradient(#95fa3c,#c4eea0,#95fa3c);
background-size:
calc(12px/0.707) 100%, /* 0.707 = cos(45deg)*/
100% 800%;
background-position:inherit;
}
@keyframes colorrush {
0% {
background-position:0 0;
}
100% {
/* the 10 multiplier will allow me to use a big duration and be able
to slow down the color animation
*/
background-position: calc(10*(12px/0.707)) 100%;
}
}
html {
font-size: 62.5%;
font-family: sans-serif;
}
body {
font-size: 1.6rem;
}
<progress max="150" value="125">125 / 150</progress>
Related question to understand the math behind the background-size
: Animated CSS background pattern, sliding infinitely
Another related one to understand the use of percentage value with background-position
: Using percentage values with background-position on a linear-gradient