How to Write CSS Keyframes to Indeterminate Material Design Progress Bar

How to write CSS keyframes to indeterminate material design progress bar

I found a good example by Stefano on CodePen:

// Android Material Loading animation with pure css. 
// Author: Stefano Ferrara http://androidpc.it/
// Forked from https://codepen.io/chofoo/pen/Abril
// Author: Simon Clavey https://simonclavey.co.uk/
body{
background:#ffffff;
margin:50px 300px;
}

.slider{
position:absolute;
width:1000px;
height:5px;
overflow-x: hidden;
}

.line{
position:absolute;
opacity: 0.4;
background:#4a8df8;
width:150%;
height:5px;
}

.subline{
position:absolute;
background:#4a8df8;
height:5px;
}
.inc{
animation: increase 2s infinite;
}
.dec{
animation: decrease 2s 0.5s infinite;
}

@keyframes increase {
from { left: -5%; width: 5%; }
to { left: 130%; width: 100%;}
}
@keyframes decrease {
from { left: -80%; width: 80%; }
to { left: 110%; width: 10%;}
}
<div class="slider">
<div class="line"></div>
<div class="subline inc"></div>
<div class="subline dec"></div>
</div>

Indeterminate progress bar in HTML+CSS

NO, NO, NO! It is possible

Using CSS overflow: hidden and keyframe, it can be possible.

For the keyframe, I used from left:-120px(width of the glowing object) to left:100%

The structure I used:

<div class="loader">
<div class="loader-bg left"></div>
<div class="loader-bg right"></div>
<div class="greenlight"></div>
<div class="gloss"></div>
<div class="glow"></div>
</div>

The updated, compact structure using :before and :after:

<div class="loader7">
<span></span>
<div class="greenlight"></div>
</div>

The gradient, masking, glowing and all the effects cost an expensive structure. If anyone has a better idea, please let me know.

At this date, webkit only solution(the ellipse mask for the glow):

Added SVG mask for Firefox and other browsers that do not support -webkit-mask-image: http://jsfiddle.net/danvim/8M24k/

Sample Image

Is it possible to render indeterminate progress bar with Twitter Bootstrap?

In bootstrap 2:

<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.2/css/bootstrap.min.css" rel="stylesheet" />
<div class="progress progress-striped active">
<div class="bar" style="width: 100%;"></div>
</div>

Sophisticated proportional triple element progress bar design using only CSS

You can do like below. I am using different colorations to better see the result

body {
margin: 100px;
background: #CCC
}

.fullbar {
background-color: blue;
}

.progress {
background: lightgreen;
margin: 10px 0 0 0;
height: 5px;
position:relative; /* relative here */
width:var(--p);
}

.number {
position:absolute; /* absolute here */
background: rgba(255,0,0,0.5);
left:100%; /* push to the right side */
transform:translateX(calc(-1*var(--p))); /* offset to the left based on --p */
top:-10px;
bottom:-10px;
color: #FFF;
padding: 0 2px 1px 3px;
}
<div class="fullbar">
<div class="progress" style="--p:0%">
<div class="number">0%</div>
</div>
</div>

<div class="fullbar">
<div class="progress" style="--p:20%">
<div class="number">20%</div>
</div>
</div>

<div class="fullbar">
<div class="progress" style="--p:50%">
<div class="number">50%</div>
</div>
</div>

<div class="fullbar">
<div class="progress" style="--p:80%">
<div class="number">80%</div>
</div>
</div>

<div class="fullbar">
<div class="progress" style="--p:100%">
<div class="number">100%</div>
</div>
</div>

Material-UI Progress hickups - css animation stops running

Animations that require a document reflow (changing margin, padding, positioning), tend to freeze when heavy calculation is going on.

The material progress bars make use of these properties to achieve their animations.

They've described this on their limitations section.

There are 3 workarounds:

  1. Animations that use transform functions aren't affected by heavy calculations
  2. Move the Heavy calculation of the render thread, using a web worker.
  3. Batch the calculation using setTimeouts, so the render thread has time to animate.

Material's circularProgress has an animation using transform. you could try to use that like :

<CircProgress disableShrink={true} />

or try moving the heavy calculations to a webworker.
You should decide for yourself if that's feasable.

This is an example using both methods

It's using 'react-webworker-hook' package to make the webworker is bit more accessible.

import React, { useState } from "react";
import LinProgress from "@material-ui/core/LinearProgress";
import CircProgress from "@material-ui/core/CircularProgress";
import { useWebWorkerFromScript } from "react-webworker-hook";

const slowFunc = () => {
var start = +new Date();
while (+new Date() - start < 2000) {}
return Math.random();
};

const MyComponent = (props) => {
const [inThreadData, setInThreadData] = useState(0);
//startHeavyRender: will block the render thread, animations will pause
const startHeavyRender = React.useMemo(
() => () => setInThreadData(slowFunc),
[]
);

//postData: will do the same calculation using a webworker, animations will continue
const [workerData = 0, postData] = useWebWorkerFromScript(`
const slowFunc = () => {
var start = +new Date();
while (+new Date() - start < 2000) {}
return Math.random();
};

onmessage = ({ data }) => {
postMessage(slowFunc());
};

`);

const startWorkerRender = React.useMemo(() => () => postData(), [postData]);

return (
<div>
<LinProgress />
<br />
<CircProgress />
<br />
<CircProgress disableShrink={true} />
<br />
<button onClick={startHeavyRender}>
start heavy render. {inThreadData}
</button>
<br />
<button onClick={startWorkerRender}>
start heavy webworker. {workerData}
</button>
</div>
);
};

export default MyComponent;

Custom color for a indeterminate progress-tag without a value

Seems like a bug to me...
When you try to apply some styles on it, Chrome seems to define the progress bar like defined, whenever it exists a value inside your tag or not.
I tried with Chrome Canary too, but same thing append.

It could be a good idea to think, "go to hell you moving item, I will erase you with my own style". But apparently,

Animations don't seem to work anymore on the pseudo elements within a progress element, in Blink. At the time this was published, they did. Brian LePore reported this to me and pointed me toward this thread discussing it and created a reduced test case.

-

Maybe it's the same with the that @keyframes defined outside of the Shadow DOM can't get accessed by an element inside. From the timing it might have changed in Chromium 39/40?

https://css-tricks.com/html5-progress-element/#article-header-id-5

So I tried but yes, animations does not work anymore...

*,*:before,*:after {  -moz-box-sizing: border-box;  -webkit-box-sizing: border-box;  box-sizing: border-box;}
html { font-family: Helvetica, Arial, sans-serif; font-size: 100%; background: #333;}
#page-wrapper { width: 640px; background: #FFFFFF; padding: 1em; margin: 1em auto; border-top: 5px solid #69c773; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.8);}
h1 { margin-top: 0;}
progress { width: 100%;}
.styled progress { /* Reset the default appearance */ -webkit-appearance: none; -moz-appearance: none; appearance: none; width: 100%; height: 15px; /* Firefox */ border: none; background: #EEE; border-radius: 3px; box-shadow: 0 2px 3px rgba(0, 0, 0, 0.2) inset;}
/* lest apply somes styles on it */.styled progress:not([value])::-webkit-progress-bar { background: blue; box-shadow: 0 2px 3px rgba(0, 0, 0, 0.2) inset; border-radius: 3px; background-image: -webkit-linear-gradient(-45deg, transparent 33%, rgba(0, 0, 0, .1) 33%, rgba(0,0, 0, .1) 66%, transparent 66%), -webkit-linear-gradient(top, rgba(255, 255, 255, .25), rgba(0, 0, 0, .25)), -webkit-linear-gradient(left, #09c, #f44); -webkit-animation: animate-stripes 5s linear infinite; animation: animate-stripes 5s linear infinite;}
/* this seems to does not work anymore */@-webkit-keyframes animate-stripes { 100% { background-position: -100px 0px; }}@keyframes animate-stripes { 100% { background-position: -100px 0px; }}
.styled progress::-webkit-progress-value { background-color: blue; border-radius: 3px;}
.styled progress::-moz-progress-bar { background-color: blue; border-radius: 3px;}
<div id="page-wrapper">  <p>Default</p>  <p>    <progress max="100"></progress>  </p>
<p>Styled defined</p> it does not move: <p class="styled"> <progress max="100" value="50"></progress> </p> <p>Styled defined</p> this should move: <p class="styled"> <progress max="100"></progress> </p>

How can I smoothly animate a Material UI LinearProgress over a fixed time period?

The example below uses CSS rather than JS to animate the progress bar over 60 seconds. It accomplishes this by using the indeterminate variant, but then customizing its CSS. The indeterminate variant leverages two bars in its animation. This example suppresses the second bar and changes the first bar to animate over 60 seconds once instead of 2.1 seconds infinitely repeating. This example also changes the keyframes part of the animation so that it ends with a full bar, rather than ending with the bar disappearing. Using forwards in the animation causes the final state to stick when the animation finishes.

import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import LinearProgress from "@material-ui/core/LinearProgress";

const useStyles = makeStyles({
root: {
width: "100%"
},
bar1Indeterminate: {
width: "auto",
animation: "$indeterminate1 60s linear forwards"
},
bar2Indeterminate: {
display: "none"
},
"@keyframes indeterminate1": {
"0%": {
left: "-35%",
right: "100%"
},
"100%": {
left: "0%",
right: "0%"
}
}
});

export default function LinearDeterminate() {
const classes = useStyles();

return (
<div className={classes.root}>
<LinearProgress
classes={{
bar1Indeterminate: classes.bar1Indeterminate,
bar2Indeterminate: classes.bar2Indeterminate
}}
variant="indeterminate"
/>
</div>
);
}

Edit 60 second progress

Relevant documentation:

  • https://developer.mozilla.org/en-US/docs/Web/CSS/animation-fill-mode
  • https://developer.mozilla.org/en-US/docs/Web/CSS/@keyframes

Here's an equivalent example using v5 of Material-UI leveraging styled and Emotion's keyframes:

import React from "react";
import { styled } from "@material-ui/core/styles";
import LinearProgress from "@material-ui/core/LinearProgress";
import { keyframes } from "@emotion/react";

const indeterminate1Keyframes = keyframes({
"0%": {
left: "-35%",
right: "100%"
},
"100%": {
left: "0%",
right: "0%"
}
});

const StyledLinearProgress = styled(LinearProgress)({
"& .MuiLinearProgress-bar1Indeterminate": {
width: "auto",
animation: `${indeterminate1Keyframes} 60s linear forwards`
},
"& .MuiLinearProgress-bar2Indeterminate": {
display: "none"
}
});

export default function LinearDeterminate() {
return (
<div style={{ width: "100%" }}>
<StyledLinearProgress variant="indeterminate" />
</div>
);
}

Edit 60 second progress



Related Topics



Leave a reply



Submit