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.1
and 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
GlobalStyles
import 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?