There are lots of ways to style a react component. But there are two ways which are quite popular among React Developers.
One is the use of Utility-first CSS frameworks like Tailwind CSS and another one is the CSS-in-JS libraries like styled-components to style react components in a JS way.
But what if we will merge them both to make a powerful way to style our components? ๐ค
Interesting, right? ๐คฉ
So here, in this tutorial we will see, how we can use them both to style react components more efficiently.
Before we start... ๐ญ
Tailwind is a utility-first CSS framework for rapidly building custom designs, directly in the markup. It helps in building complex components from a constrained set of primitive utilities.
twin.macro is a library that helps to combine Tailwind CSS with libraries like emotion and styled-components to give more power to style React components.
So if you are using styled-components and want to power your styling with Tailwind CSS or you are a React beginner and want to learn a magic to style your React Components, then this article is for you.
Note: This article is based on Tailwind CSS 2.0. It may not work with other versions of Tailwind CSS.
What will we build? ๐ค
In this article, we will demonstrate a combination of twin.macro and styled-components to style our React Components. After this, you can easily style your React Components more efficiently for sure.
Prerequisites ๐
- Basic knowledge of React JS.
- Basic knowledge of CSS.
- Node version
v14.15.1and npm version6.14.8. It may not work properly in the lower version of Node.
If you have these, Let's get started ๐
Letโs Begin ๐
1. Setup our Project
Step - 1 : Create our app
First, Let's create our project with create-react-app by running:
npx create-react-app react-styling-tutorial
After project creation, let's open our project in VS Code (or any other Code Editor/ IDE).
Step - 2 : Install required dependencies
Now, let's install twin.macro, tailwindcss & styled-components in our project by running:
npm i --save twin.macro tailwindcss styled-components
Here all of my dependencies with their versions:
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-scripts": "4.0.1",
"styled-components": "^5.2.1",
"tailwindcss": "^2.0.1",
"twin.macro": "^2.0.6",
Note: Please make sure to have the same version of dependencies to avoid errors.
Step - 3 : Configure Tailwind
After installing all the above dependencies, let's create Tailwind config file named tailwind.config.js in our src directory by running:
npx tailwind init src/tailwind.config.js
The generated file will look like below:
module.exports = {
purge: [],
darkMode: false, // or 'media' or 'class'
theme: {
extend: {},
},
variants: {
extend: {},
},
plugins: [],
};
As you can see, the config file is "empty" since there is no configuration. If you want a full version of the tailwind config, then you can run:
npx tailwind init src/tailwind.config.js --full
Step - 4 : Configure Twin
Now let's go to our package.json and add the following twin configuration:
"babelMacros": {
"twin": {
"config": "./src/tailwind.config.js",
"preset": "styled-components"
}
},
This configuration will help to transform tailwind classes into CSS-in-JS code.
Great! Let's run our app to ensure everything is fine by running:
npm start
Here is what our app will look like in the browser (or similar).

2. Create Components
Okay. Let's first stop our web server.
Now remove App.css, logo.svg from the src directory to clean our project a little bit.
src directory will look like:
.
|____App.js
|____App.test.js
|____index.css
|____index.js
|____tailwind.config.js
|____reportWebVitals.js
|____setupTests.js
Now let's modify App.js as below:
import React from 'react';
const App = () => {
return <h1>My App Component</h1>;
};
export default App;
Now if you will run the app again, it will work absolutely fine with no errors ๐
Great. Next, create a directory, named components inside the src directory.
And inside the components directory let's create another directory named Button.
Now inside our Button directory, create an index.js file.
src directory will look like:
.
|____components
| |____Button
| | |____index.js
|____App.js
|____App.test.js
|____index.css
|____index.js
|____tailwind.config.js
|____reportWebVitals.js
|____setupTests.js
Next, inside the src/components/Button/index.js let's write our button component as below:
import React from 'react';
const ButtonComponent = () => {
return <button>Click Me!</button>;
};
export default ButtonComponent;
Now, let's come back to src/App.js and import our ButtonComponent
import React from 'react';
import ButtonComponent from './components/Button'; // new
const App = () => {
return (
// new
<div>
<ButtonComponent />
</div>
);
};
export default App;
Here is what our app will look like in the browser.
You can see our button component is here ๐คฉ
3. Setup Theme
Okay. We are doing great so far. Now let's set up our theme for our project.
Let's stop our server and goto /src/index.css and put the following css at the top:
:root {
--color-primary: #4ff0c9;
--color-secondary: #172a45;
--color-white-alt: #ccd6f6;
}
Here we have created 3 variables to store colors, named --color-primary, --color-secondary, and --color-white-alt.
Now add our colors inside the theme in /src/tailwind.config.js like below:
module.exports = {
purge: [],
darkMode: false,
theme: {
extend: {
colors: { // new
primary: 'var(--color-primary)', // new
secondary: 'var(--color-secondary)', // new
whiteAlt: 'var(--color-white-alt)', // new
}, // new
},
},
variants: {
extend: {},
},
plugins: [],
};
Great!!! Let's first run our app and check, everything is fine or not.
We got the same result as before ๐ค
4. Style Components
Let's create a styles directory inside our src directory and create a file named StyledApp.js inside the styles directory for styling our App component.
Finally, our src directory will look like:
.
|____components
| |____Button
| | |____index.js
|____styles
| |____StyledApp.js
|____App.js
|____App.test.js
|____index.css
|____index.js
|____tailwind.config.js
|____reportWebVitals.js
|____setupTests.js
Now, open the StyledApp.js and let's write some styling for our App component.
import tw, { styled } from 'twin.macro';
export const StyledApp = styled.div`
${tw`flex justify-center items-center h-screen`}
`;
Next, come back to App.js and import our StyledApp as below:
import React from 'react';
import ButtonComponent from './components/Button';
import { StyledApp } from './styles/StyledApp'; // new
const App = () => {
return (
<StyledApp> {/* new */}
<ButtonComponent />
</StyledApp>
);
};
export default App;
Now save and look at your browser, the button comes to the center of the screen.
Taddddda!!! As you can see, our styling for our App component is working perfectly ๐
We can also use GlobalStyles in our App component as below:
import React from 'react';
import ButtonComponent from './components/Button';
import { GlobalStyles } from 'twin.macro'; // new
import { StyledApp } from './styles/StyledApp';
const App = () => {
return (
<div>
<GlobalStyles /> {/* new */}
<StyledApp>
<ButtonComponent />
</StyledApp>
</div>
);
};
export default App;
Now our app will look like:
You can see, the style of our Button component is changed because of the GlobalStyles.
Amazing! Now let's style our ButtonComponent. Create another file named StyledButton.js inside /src/styles.
src/styles directory will look like:
.
|____StyledApp.js
|____StyledButton.js
Write some styling inside our StyledButton.js for our button component.
import tw, { styled } from 'twin.macro';
export const StyledButton = styled.button`
${tw`py-3 px-8 uppercase rounded border border-primary hover:bg-primary`}
`;
Next, go back to /src/components/Button/index.js and import our StyledButton as below:
import React from 'react';
import { StyledButton } from '../../styles/StyledButton'; // new
const ButtonComponent = () => {
return <StyledButton>Click Me!</StyledButton>; // new
};
export default ButtonComponent;
Now you can see our Styled Button in our browser.
Now here if you want to add your custom CSS for ButtonComponent you can do that inside /src/styles/StyledButton.js as below :
import tw, { styled } from 'twin.macro';
export const StyledButton = styled.button`
${tw`py-3 px-8 uppercase rounded border border-primary hover:bg-primary duration-200`}; // added duration-200 (optional)
& {
background-color: yellow;
}
&:hover {
font-size: 2rem;
}
`;
We can also access theme data directly like below:
import tw, { styled, theme } from 'twin.macro'; // new
export const StyledButton = styled.button`
${tw`py-3 px-8 uppercase rounded border border-primary hover:bg-primary duration-200`}; // added duration-200 (optional)
& {
background-color: ${theme`colors.whiteAlt`}; // modified
}
&:hover {
font-size: 2rem;
}
`;
Now you can see the background color of the button is changed.
4. Conditional Styling
Let's change our styling with conditions.
To do that, let's change our StyledButton.js as below:
import tw, { styled, theme, css } from 'twin.macro'; // modified
export const StyledButton = styled.button(() => [
tw`py-3 px-8 uppercase rounded border border-primary hover:bg-primary duration-200`,
css`
& {
background-color: ${theme`colors.whiteAlt`};
}
&:hover {
font-size: 2rem;
}
`,
]);
It will give us the same output as before ๐ค
Okay. Let's add a condition.
We will style our button differently if isSecondary is true.
Here is our final code will look like:
import tw, { styled, theme, css } from 'twin.macro';
export const StyledButton = styled.button(({ isSecondary }) => [
// updated
tw`py-3 px-8 uppercase rounded border border-primary hover:bg-primary duration-200`,
css`
& {
background-color: ${theme`colors.whiteAlt`};
}
&:hover {
font-size: 2rem;
}
`,
isSecondary && tw`border-secondary hover:bg-secondary hover:text-white`, // new
]);
Now let's go back to ButtonComponent in src/components/Button/index.js and pass the isSecondary parameter in StyledButton like below:
const ButtonComponent = () => {
return <StyledButton isSecondary>Click Me!</StyledButton>; // modified
};
export default ButtonComponent;
Awwwwwesome! Isn't it? ๐
Conclusion ๐
Here is my Github repo for your reference - https://github.com/devsmranjan/react-tailwindcss-styledcomponents-template
You can use this as a template for your next project ๐
Thank you for reading my article ๐ . I hope you have learned something here.
Happy coding ๐จโ๐ป๐ฉโ๐ป and stay tuned for my next post.
Thanks! Don't forget to give a โฅ๏ธ and follow :)
















Top comments (9)
Nice post, actually you don't need to "compile" tailwindcss as twin.macro does it behind the scenes.
The only thing you need in your project is twin.macro and styled-components
Thanks for appreciating this post.
I'll surely improve this article in the next few days.
I just finished the project where I integrated tailwindcss into Svelte.
Recently I was debating whether to use Material UI React kit vs integrating tailwindcss in React in my new project. You are spot on! Now I'm definitely trying your approach.
Great job, brother ๐ค
I landed here after I found out that TailwindCSS could be messy and thought if I could use this with Styled Component. Great article to make me understand how to use both together with simplicity! Thanks for sharing!
What does
<GlobalStyles />do?Basically,
<GlobalStyles />provides a base style to our app.Twin uses the same preflight base styles as Tailwind to smooth over cross-browser inconsistencies.
The
GlobalStylesimport adds these base styles along with some @keyframes for the animation classes and some global css that makes the ring classes and box-shadows work.Same thought too
What is the purpose of tailwing.config.js file?