I just want to know if there is a way to use framer-motion with Material-Ui. I tried but I am not getting it.
5 Answers
Material-UI
has component
prop option for this kind of requirement and should do better and more elegant approach than the wrapping-approach. Then, you can pass any props provided by framer-motion
package to your Material-UI
component as long as they're not conflicted (i'm not sure if any).
<Button
color="inherit"
variant='contained'
size="large"
component={motion.div}
whileHover={{
scale: 1.2,
transition: { duration: 0.3 }
}}
whileTap={{ scale: 0.9 }}
>
Button
</Button>

- 576
- 5
- 4
Your question made me curious. I never tried the framer-motion, but was planning to learn it recently.
So I gave it a try, created a sandbox, added a Material UI and framer motion packages in it.
Just created a small button in the middle of the page using Material UI. And wrapped the button using <motion.div>
tag, like this:
import React from "react";
import { motion } from "framer-motion";
import Button from "@material-ui/core/Button";
function AnimatableDiv() {
return (
<motion.div
className="animatable"
whileHover={{
scale: 1.2,
transition: { duration: 0.3 }
}}
whileTap={{ scale: 0.9 }}
>
<Button size="large" className="animatable">
Button
</Button>
</motion.div>
);
}
export default AnimatableDiv;
And it worked!
You might be thinking what if I use the the motion.
directly on the <Button>
component, like this:
<motion.Button size="large" className="animatable">
Button
</motion.Button>
Well, I did think of this, and I applied it as well and all the styling that Material UI applied to that button were lost! So do not follow this approach! I repeat do not!
Here's the link can have a look at it: https://codesandbox.io/s/brave-sutherland-5bki9

- 1,322
- 10
- 17
-
Thank You!! I think wrapping is the only option. – Satyam Dec 11 '20 at 14:41
I was also in the same situation, so after a small research, and some trial and error I wrote a small article on this, hope you guys get helped from this, and if any suggestion feels free to elaborate in the comment section.
https://aishmn.medium.com/how-to-use-material-ui-and-framer-motion-together-6026fed96a4c

- 66
- 4
The accepted answer's strategy is the easiest way to implement this but another strategy is to use framer-motion's wrapping.
This is my implementation with Typescript for those who might search for this problem.
Box.tsx
import React from "react";
import { motion } from "framer-motion";
import MuiBox, { BoxProps } from "@mui/material/Box";
const BoxComponent = React.forwardRef((props: BoxProps, ref) => (
<MuiBox {...props} ref={ref} />
));
const Box = motion(BoxComponent);
export default Box;
Then use it in your component
import Box from "./Box";
// The motion-wrapped Mui Box now also accepts framer-motion's props
<Box
initial={{ opacity: 0 }}
animate={{ x: 100, rotate: [null, 10, 20], opacity: 1 }}
whileHover={{ scale: [null, 1.5, 1.4] }}
width={100}
height={100}
border="1px solid red"
/>

- 107
- 7
-
This works best with Nextjs because `component={motion.div}` throws a hydration error in Nextjs – Ilir Feb 02 '23 at 10:33
-
This look like the best approach and also recommended by framer-motion doc (https://www.framer.com/motion/component/#custom-components), currently. Mine was almost 2 years ago and might be out-dated (or may be used as work-around for quick fix or basic requirements) due to the fact that things are changing frequently in this eco-system. – Ramazan Çağrı AKAR Feb 23 '23 at 05:59
I had the same question so i digged a little bit in the motion doc. and i found this: Any component can be turned into a motion component by wrapping it with the motion() function. So i did this:
import { TextField } from "@mui/material";
import { motion } from "framer-motion";
export default function YourComponent() {
const TextFieldMotion = motion(TextField);
return (
<TextFieldMotion
animate={{ x: [0,20] }}
transition = {{ ease: "easeInOut", duration: 3 }}
variant="filled"
label="first name"
/>
)
};
for more information: https://www.framer.com/docs/component/

- 76
- 1
- 5