Modern web applications require a contemporary look and feel. The days of using plain HTML and CSS are long gone. In the last few years, JavaScript has evolved, and so have browsers.
In today’s web world, the front end no longer uses jQuery. Developers use modern UI libraries like React or Vue, which support creating transitions and animations while keeping the user interface looking nice and clean.
Let’s understand animation and transition.
What is an Animation?
Animation is a type of user experience element that creates dynamic and visually appealing effects that change the appearance or behavior of elements over time.
Common examples of animation are fading, scaling, sliding, and rotating.
What is a Transition?
To create a perfect animation, you need to create a transition.
Transition is the process of changing the state from one to another. If you have worked with form elements, you often see dynamically appearing input elements based on a click event. For example, if you want to upload multiple images, you would create an “Add Button”, which will populate more fields.
Showing or hiding elements based on some events counts as a transition because it happens after a user interacts with the app.
You can create various types of animation and smooth transitions to enhance user experience, resulting in a lower bounce rate and more engagement.
Material UI’s Built-in Support
Material-UI provides several built-in transition components that you can use to create fantastic animations.
Here are the transition components that we will use in our project to create an animation:
- Collapse: As the name suggests, it collapses or expands an element vertically.
- Fade: You must have heard of the fading-in or fading-out effect, meaning an element gradually changes its opacity.
- Grow: Again, as names suggest, it expands an element from small to large or full size.
- Slide: It moves an element in and out of the view along the X or Y-axis. Basically, if you have seen a slider of images, then this might be the component behind it.
- Zoom: It scales an element in and out. In short, Zoom-in, Zoom-out type of animation.
Simple Project
Let’s create a simple React project where we create an animated card, face-in text, and rotating material icon like below GIF:
You can see the “Animated Card”‘s animation, fade-in text “Welcome to MUI Animations”, and “Star” rotating icon.
Here is the step-by-step guide to creating a project:
Step 1: Initialize a React project
You initialize a new React project using the command below:
npm create vite@latest mui-animations -- --template react-ts
Here, you can see that we created a new Vite project of React with TypeScript support.
Go inside the project folder and install the dependencies:
cd mui-animations npm install
Step 2: Install MUI dependencies
Now, let’s install the necessary Material UI packages:
npm install @mui/material @emotion/react @emotion/styled @mui/icons-material
Step 3: Create a “Grow” transition
Let’s create a “Grow” transition in which it expands the “Card” component to a big size, constructing an animation effect.
Under the “src” folder, create a new folder called “components”. Inside that folder, create a new file called “AnimatedCard.tsx”. This is a reusable functional component.
// src/components/AnimatedCard.tsx import React from "react"; import { Card, CardContent, Typography, Grow } from "@mui/material"; interface AnimatedCardProps { title: string; content: string; } const AnimatedCard: React.FC<AnimatedCardProps> = ({ title, content }) => { const [isVisible, setIsVisible] = React.useState(false); React.useEffect(() => { setIsVisible(true); }, []); return ( <Grow in={isVisible} timeout={1000}> <Card sx={{ minWidth: 275, m: 2 }}> <CardContent> <Typography variant="h5" component="div"> {title} </Typography> <Typography variant="body2">{content}</Typography> </CardContent> </Card> </Grow> ); }; export default AnimatedCard;
To create a “Grow” transition, we need to import “Grow” from @mui/material library.
In the above code, we define the AnimatedCard functional component that accepts AnimatedCardProps as its props type.
To control the visibility, we defined the isVisible state variable.
Then, we defined the useEffect hook that sets isVisible to true after the component mounts, triggering the Grow transition.
The Grow is a MUI component that applies a grow animation to its children. The “in” prop controls whether the component is visible or not, and timeout sets the duration of the animation (1000 milliseconds in this case).
Basically, when the AnimatedCard is mounted, it creates a card that animates into view with a grow effect.
Step 4: Create a “Fade” transition
Under the “components” folder, create a new file called “FadeInText.tsx” and add the code below:
// src/components/FadeInTextProps.tsx import React from "react"; import { Typography, Fade } from "@mui/material"; interface FadeInTextProps { text: string; } const FadeInText: React.FC<FadeInTextProps> = ({ text }) => { const [isVisible, setIsVisible] = React.useState(false); React.useEffect(() => { setIsVisible(true); }, []); return ( <Fade in={isVisible} timeout={1500}> <Typography variant="h4" component="div" sx={{ m: 2 }}> {text} </Typography> </Fade> ); }; export default FadeInText;
We imported the “Fade” component from the MUI library to create a fade-in animation.
We created a FadeInText functional component that accepts FadeInTextProps.
We control the visibility of the text using the isVisible state, which is set to true after the component mounts using the useEffect hook. This results in a smooth fade-in animation over 1.5 seconds. The rest of the description is the same as the above step.
Step 5: Rotating using keyframes
The keyframes is a utility from emotion (a CSS-in-JS library) to define keyframe animations.
You can define keyframe animation using Emotion’s keyframes function. It rotates an element from 0deg to 360deg continuously.
Under the “components” folder, create a new file called “RotatingIcon.tsx” and add the code below:
// src/components/RotatingIcon.tsx import React from "react"; import { IconButton, Tooltip } from "@mui/material"; import { Star as StarIcon } from "@mui/icons-material"; import { keyframes } from "@emotion/react"; const rotate = keyframes` from { transform: rotate(0deg); } to { transform: rotate(360deg); } `; const RotatingIcon: React.FC = () => { return ( <Tooltip title="Rotating Star"> <IconButton sx={{ animation: `${rotate} 2s linear infinite`, "&:hover": { animation: `${rotate} 1s linear infinite`, }, }} > <StarIcon /> </IconButton> </Tooltip> ); }; export default RotatingIcon;
In short, we created the RotatingIcon component to create a continuously rotating icon button. When the user hovers over the button, the rotation speed increases.
Step 6: Update the App.tsx component
Now, let’s update the src/App.tsx file to use these components:
// src/App.tsx import React from "react"; import { Container, Box } from "@mui/material"; import AnimatedCard from "./components/AnimatedCard"; import FadeInText from "./components/FadeInText"; import RotatingIcon from "./components/RotatingIcon"; const App: React.FC = () => { return ( <Container maxWidth="sm"> <Box sx={{ my: 4 }}> <FadeInText text="Welcome to MUI Animations!" /> <AnimatedCard title="Animated Card" content="This card appears with a grow animation." /> <Box sx={{ display: "flex", justifyContent: "center", mt: 2 }}> <RotatingIcon /> </Box> </Box> </Container> ); }; export default App;
And update the main entry src/main.tsx file:
// src/main.tsx import React from "react"; import ReactDOM from "react-dom/client"; import { ThemeProvider, createTheme, CssBaseline } from "@mui/material"; import App from "./App"; const theme = createTheme(); ReactDOM.createRoot(document.getElementById("root")!).render( <React.StrictMode> <ThemeProvider theme={theme}> <CssBaseline /> <App /> </ThemeProvider> </React.StrictMode> );
That’s all!