
Data Structure
Networking
RDBMS
Operating System
Java
MS Excel
iOS
HTML
CSS
Android
Python
C Programming
C++
C#
MongoDB
MySQL
Javascript
PHP
- Selected Reading
- UPSC IAS Exams Notes
- Developer's Best Practices
- Questions and Answers
- Effective Resume Writing
- HR Interview Questions
- Computer Glossary
- Who is Who
Use Tailwind CSS with Variants in Framer Motion
Combining Tailwind CSS for styling and Framer Motion for animations can be challenging because Tailwind uses static utility classes, while Framer Motion relies on dynamic animation variants. This can create conflicts and make it difficult to integrate both smoothly in a React project.
Our task is to find a way to use Tailwind's styles with Framer Motion's animations without conflicts, allowing smooth integration in a React project.
Approaches
we will cover different approaches to integrate Tailwind CSS with FramerMotion, explained step by step for smooth styling and animations in your React project.
- Using className with Framer Motion's motion components
- Using variants with conditional classes
- Using dynamic variants with Tailwind classes
- Using layout animations with Tailwind
Steps to Setup
Before we start with the approaches, you need to set up your environment and install the required dependencies. This includes setting up Tailwind CSS and Framer Motion in your React project.
First, create a new React app using create-react-app:
npx create-react-app tailwind-motion-demo cd tailwind-motion-demo
After creating the app, install React 18 and ReactDOM 18 to avoid version conflicts:
npm install react@18 react-dom@18
Now, install Tailwind CSS and its dependencies:
npm install -D tailwindcss postcss autoprefixer
Run the following command to initialize the Tailwind CSS configuration:
npx tailwindcss init
Open tailwind.config.js and modify the content array to look like this:
module.exports = { content: [ './src/**/*.{js,jsx,ts,tsx}', // Ensure Tailwind scans all your React files ], theme: { extend: {}, }, plugins: [], }
Open src/index.css (create it if it doesn't exist) and add the following Tailwind directives:
/* src/index.css */ @tailwind base; @tailwind components; @tailwind utilities;
Make sure src/index.css is imported into src/index.js:
import './index.css'; // This imports the Tailwind CSS into your React project
Next, install Framer Motion for animations:
npm install framer-motion
Using className with Framer Motion's motion components
This approach uses Tailwind CSS for styling and Framer Motion's motion components for animations. Here are the steps we followed:
First, we create or update MyComponent.js in /src/components/:
import { motion } from 'framer-motion'; const MyComponent = () => { return ( <motion.div className="bg-purple-500 p-6 rounded-lg shadow-2xl border border-fuchsia-900" animate={{ scale: 1.2 }} // Animation: scale to 1.2 transition={{ duration: 0.5 }} // Duration of animation: 0.5 seconds > <h1 className="text-white text-xl">Hello, Framer Motion!</h1> </motion.div> ); }; export default MyComponent;
Next, we use MyComponent in App.js:
import React from 'react'; import MyComponent from './components/MyComponent'; function App() { return ( <div className="App flex justify-center items-center h-screen bg-gray-100"> <MyComponent /> </div> ); } export default App;
Then, we run the following command in the terminal:
npm start
Output

Using Variants with Conditional Classes
In this approach, we'll animate the component based on a condition, dynamically changing the Tailwind classes according to the animation state. Steps we have taken include:
First, we update MyComponent.js to include variants:
import { motion } from 'framer-motion'; import { useState } from 'react'; const MyComponent = () => { const [isVisible, setIsVisible] = useState(false); const variants = { hidden: { opacity: 0, scale: 0 }, visible: { opacity: 1, scale: 1 } }; // Conditional class for background const boxClass = isVisible ? 'bg-green-500' : 'bg-red-500'; return ( <div className="flex justify-center items-center h-screen"> <motion.div // Apply dynamic class className={`p-6 rounded-lg ${boxClass}`} variants={variants} animate={isVisible ? 'visible' : 'hidden'} transition={{ duration: 0.5, ease: 'easeInOut' }} > <h1 className="text-white text-center"> Animated Box& lt;/h1> </motion.div> {/* Toggle Button */} <div className="mt-5"> <button onClick={() => setIsVisible(!isVisible)} className="px-2 py-2 bg-purple-500 text-white rounded-lg" > Toggle Visibility </button> </div> </div> ); };
Now, use this MyComponent in App.js as before.
Finally, run the application by opening the terminal and executing the following command:
npm start
Output

Using dynamic variants with Tailwind classes
In this approach, we will use Framer Motion's animation states to change Tailwind classes, allowing the component's appearance to update smoothly based on its state. Below are the steps we took:
We start by updating the MyComponent.js file to handle dynamic animation states and apply Tailwind classes based on the current animation state.
import { motion } from 'framer-motion'; import { useState } from 'react'; const MyComponent = () => { const [isClicked, setIsClicked] = useState(false); const variants = { start: { backgroundColor: 'rgb(34, 197, 94)' }, // green-500 end: { backgroundColor: 'rgb(239, 68, 68)' } // red-500 }; return ( <motion.div className="p-6 rounded-lg" animate={isClicked ? 'end' : 'start'} variants={variants} transition={{ duration: 0.5 }} onClick={() => setIsClicked(!isClicked)} > <h1 className="text-white"> Click to Change Color </h1> </motion.div> ); }; export default MyComponent;
Once we have updated MyComponent.js, we can use it in your App.js file as follows:
import React from 'react'; // Import MyComponent import MyComponent from './MyComponent'; function App() { return ( <div className="App"> {/* Use MyComponent in App.js */} <MyComponent /> </div> ); } export default App;
Run the app to see the background color change when clicking the component.
npm start
Output

Using Layout Animations with Tailwind
In this approach, we will use Framer Motion's layout prop to animate layout changes like resizing or repositioning an element. Below are the steps we took:
Update MyComponent.js to use the layout prop, which makes the component resize when the isLarge state changes after clicking.
import { motion } from 'framer-motion'; // Import Framer Motion for layout animations import { useState } from 'react'; // Import useState to manage the size state const MyComponent = () => { // Track whether the component is large const [isLarge, setIsLarge] = useState(false); return ( <motion.div // Change width based on state className={`p-6 rounded-lg ${isLarge ? 'w-64' : 'w-32'} bg-blue-500`} layout // Enable layout animation // Toggle size on click onClick={() => setIsLarge(!isLarge)} // Set the duration of the resize animation transition={{ duration: 0.5 }} > <h1 className="text-white">Click to Resize</h1> </motion.div> ); }; export default MyComponent;
Then, we run the following command in the terminal:
npm start
Output
