I'm trying to setup a simple animation with keyframes as explained on JSS but with no luck:
const MyComponentWithStyles = withStyles(() => ({
"@keyframes fadeAnimation": {
from: {opacity: 0},
to: {opacity: 1},
},
container: {
width: "100px",
height: "100px",
background: "red",
animation: "1s fadeAnimation",
}
}))(MyComponent)
After making some searches I found this FAQ question where it says to use a 'CSS alternative' for keyframe animations. I'm not sure what is intended by 'CSS alternative'. Conventional CSS styling?
Also, this pull request has a comment which says keyframe animations don't work. Not sure how relevant this comment is for my issue.
Yes, keyframes work. We use them internally: https://github.com/mui-org/material-ui/blob/353c0aedc50de8bb2c09626e520d7cc16ac461dc/packages/material-ui/src/ButtonBase/TouchRipple.js#L84
I ran across this issue just now. According to the JSS docs, one is supposed to put a $
in front of the animation name, which doesn't work. Simply omitting it, just as in your example above, works fine.
@bjrn It depends on the version of JSS you are using.
For posterity: using a keyframes inside a makeStyles
was not working.
The generated animation name was something like makeStyles-keyframes-glowIcon-187
while the animation name placed on CSS rule was simply glowIcon
(name used in the JS).
In my environment putting the $
cited by @bjrn fixed the issue:
animation: '$glowIcon 2000ms infinite',
For people experiencing this issue:
https://cssinjs.org/jss-syntax/?v=v10.0.0-alpha.10#keyframes-animation
I found one more issues: makeStyles (used as react hook) + function at the style rule level
animation
generation crashes: animation: ({ duration }) => `$glitch ${duration}s infinite`
Output:
.makeStyles-root-470::before {}
animation-name
without ref char ($
) I can see that rules being generated to animation
, but animation-name
doesn't refer to @keyframe
properly.animation: ({ duration }) => `glitch ${duration}s infinite`
Output:
.makeStyles-root-477::before {
animation: 1s ease 0s infinite normal none running glitch;
}
animation: `$glitch 5s infinite`,
Output:
.makeStyles-root-482:before {
animation: makeStyles-keyframes-glitch-483 5s infinite;
}
animationDuration: ({ duration }) => `${duration}s`,
animationIterationCount: 'infinite',
animationName: `$glitch`,
"@material-ui/core": "^4.1.3",
"@material-ui/icons": "^4.4.1",
"@material-ui/styles": "^4.1.1",
Also TS complains about using function at the style rule level :(
makeStyles()
:sslider: ({urls}) => ({
background: `url(${urls[0]})`,
backgroundRepeat: "no-repeat",
animation: `$slidingBackgroundAnimation 10s`,
...
}),
"@keyframes slidingBackgroundAnimation": {
from: {
backgroundPositionX: "0px",
},
to: {
backgroundPositionX: "-100px",
},
},
Here the name of the animation keyframes
is rendered badly. Like if the actual animation keyframe slidingBackgroundAnimation
is rendered in <head> > <style>
as @-webkit-keyframes makeStyles-keyframes-slidingBackgroundAnimation-108
but the sslider
css would reference it badly like @-webkit-keyframes makeStyles-keyframes-slidingBackgroundAnimation-109
(with different number).
sslider: {
background: ({ urls }) => `url(${urls[0]})`,
backgroundRepeat: "no-repeat",
animation: `$slidingBackgroundAnimation 10s`,
....
},
"@keyframes slidingBackgroundAnimation" : { ... }
Also, it was huge pain to try to dynamically render @keyframes animationName
using props property by using makeStyles({})
passing the props via useStyles({})
.
This was the code that didn't work.
const imageSliderAlgo = (urls) => {
// a function that accepts urls and dynamically create object to be consumed by the keyframes
// return example for two images
return {
"0%": { backgroundImage: `url(${urls[0]})` },
"50%": { backgroundImage: `url(${urls[1]})` }
}
};
const useStyles = makeStyles(theme => ({
"@keyframes slidingBackgroundImageAnimation": ({ urls }) =>
imageSliderAlgo(urls),
sslider: { ... }
});
It was not able to get the props, I guess it is due to the fact that props are not properly passed over classNames
or higher selectors but works fine when referring the props in the CSS property (as shown by the code in the above section).
After a lot of trials and errors and burning a lot of time, I figured out the best way to get around and dynamically render the keyframes in css-in-js style was wrapping the useStyles()
in a custom hook and returning the makeStyles()
from there.
const useMyStyles = props => {
const useStyles = makeStyles(theme => ({
sslider: {
background: ({ urls }) => `url(${urls[0]})`,
animation: `$slidingBackgroundAnimation 30s ease 2s infinite forwards, $slidingBackgroundImageAnimation 20s ease 2s infinite forwards`,
...
},
// animation 1
// dynamically rendering keyframes in css-in-js
// using the props property passed in custom useMyStyles hook while invoking it in main component
"@keyframes slidingBackgroundImageAnimation": imageSliderAlgo(props.urls),
// animation 2
// static keyframes in css-in-jss
"@keyframes slidingBackgroundAnimation": {
"0%": {
backgroundPositionX: "0px",
},
"50%": {
backgroundPositionX: "-120px",
}
},
})); // useStyles closed
// returning useStyle function with the props passed in the higher order/parent function
return useStyles(props);
} // useMyStyles custom hook closed
// Component
export default function SlidingBackground({ children, urls }) {
// non-working way
// const classes = useStyles({ urls });
// working way
const classes = useMyStyles({ urls });
return (
<>
<div className={classes.sslider}>{children}</div>
</>
);
}
Sometimes all that is needed is a custom hook or basically custom function.
For posterity: using a keyframes inside a
makeStyles
was not working.The generated animation name was something like
makeStyles-keyframes-glowIcon-187
while the animation name placed on CSS rule was simplyglowIcon
(name used in the JS).In my environment putting the
$
cited by @bjrn fixed the issue:animation: '$glowIcon 2000ms infinite',
you save my day
Sometimes all that is needed is a custom hook or basically custom function.
Made no difference for me
Most helpful comment
For posterity: using a keyframes inside a
makeStyles
was not working.The generated animation name was something like
makeStyles-keyframes-glowIcon-187
while the animation name placed on CSS rule was simplyglowIcon
(name used in the JS).In my environment putting the
$
cited by @bjrn fixed the issue: