Introduction
In this post, I'll explain what's Tailwind CSS and Twin. As well I'll explain how to integrate them to make use of Tailwind CSS with the power of CSS-IN-JS.
What is Tailwind CSS?
Maybe this is the first time you've heard about Tailwind CSS, so I'll briefly explain what is.
Tailwind CSS is a CSS Framework like Bootstrap but with the difference that Tailwind CSS doesn't have any kind of "components" orientation like Bootstrap.
The great feature of this framework is that it's oriented to "utilities" and thanks to this it gives us full customization of your designs, because of that you don't have to deal with the problem of styles imposed by other frameworks or trying to overwrite classes.
These "utilities" are basically small blocks that allow us to build our site with precision. To make it clearer, below you can see an example of how the HTML code looks with the help of Tailwind CSS:
<div class="mt-10 ml-10">
<button class="px-6 py-3 bg-blue-500 font-bold text-white rounded shadow">
I'm a Button!
</button>
</div>
Output:
Well as you can see, to build a button we must write each small "block" that allows us to style our button, which is very different from Bootstrap in which we already have a class called .btn
which provides us the design of a button.
Tailwind CSS with CSS-IN-JS in a ReactJS project
So, let's go back to the main objective of this post, explain how to install and configure Tailwind CSS with CSS-IN-JS on a ReactJS project.
Setting up our ReactJS Project
The first step is to generate or create our React project. In this case, I gonna use the create-react-app package. So, we need to run the following command in our terminal or cmd:
npx create-react-app reactapp-with-tw
Once the project is created, enter in the project folder with:
cd path/to/your/project
Install dependencies
Now that we have our React project ready, let's proceed to install some dependencies that we're going to need and use.
Put the following command in your terminal or cmd:
npm install twin.macro styled-components
# or
yarn add twin.macro styled-components
- twin.macro: It's a library which basically converts your Tailwind CSS classes intro CSS objects and shares them with styled-components or emotion to give us the power of writing with CSS-IN-JS.
- styled-components: is a library for React and React Native that allows you to use component-level styles in your application that is written with a mixture of JavaScript and CSS using a technique called CSS-in-JS
Configuration file of Tailwind CSS
As I mentioned in the description of each package, twin reads our configuration file to convert Tailwind CSS classes into CSS objects.
So, let's proceed to create a configuration file for Tailwind CSS. Inside our project folder, run the following command in your terminal or cmd:
npx tailwindcss init
# You can add the --full flag if you want to see the full configuration file of Tailwind CSS
This is the content of the file that was just generated:
// tailwind.config.js
module.exports = {
future: {
removeDeprecatedGapUtilities: true,
purgeLayersByDefault: true,
defaultLineHeights: true,
standardFontWeights: true
},
purge: [],
theme: {
extend: {}
},
variants: {},
plugins: []
};
Is important to clarify that Twin only reads the theme
and plugin
values.
Set our custom configuration file path
In this step, we need to set the path of our tailwind.config.js
file, you can do this step in two ways:
Go to your
package.json
file and put the following code:// package.json "babelMacros": { "twin": { "config": "tailwind.config.js", "preset": "styled-components", "autoCssProp": true, "debugProp": true, "debugPlugins": false, "debug": false, } },
Create a new file called
babel-plugin-macros.config.js
in our project root:// babel-plugin-macros.config.js module.exports = { twin: { config: "tailwind.config.js", preset: "styled-components", autoCssProp: true, debugProp: true, debugPlugins: false, debug: false } };
Using global styles in our project
Projects using Twin also use the Tailwind preflight base styles to smooth over cross-browser inconsistencies.
Twin has a component to add these styles to our project, go to your entry file or App.js
and add the following code:
// src/App.js
import { GlobalStyles } from 'twin.macro';
const App = () => (
<>
<GlobalStyles />
{/* more code */}
</>
);
export default App;
Using Tailwind CSS with Twin
So now, here is some examples of the things that you can do using Tailwind CSS and Twin.
Prop to JSX Elements
You can pass the tw
prop into JSX elements, a good way if you have an element without a lot of classes.
import 'twin.macro';
export default function App() {
return (
<h1 tw="text-2xl text-blue-500 font-bold">Hello world</h1>
);
}
Nesting tw
with css
prop
In this case, you can pass de css
prop to a JSX Element in order to create conditional styles.
In the example, we have a variable called isBold and basically in the css
prop check if the isBold is true. If it's true then we will have an element with font-bold
class.
import tw from 'twin.macro';
export default function App() {
const isBold = true;
return (
<h1 css={[tw`text-3xl text-blue-500`, isBold && tw`font-bold`]}>Hello world</h1>
);
}
Mixing SASS styles with the css
import
With the css
import, we can mix SASS style with our TailwindCSS classes.
import tw, { css } from 'twin.macro';
export default function App() {
const myCustomStyles = css`
${tw`font-bold`}
&:hover {
font-weight: 500;
${tw`text-black`}
}
`;
return (
<h1 css={[tw`text-3xl text-blue-500`, myCustomStyles]}>Hello world</h1>
);
}
Styled Components
With the tw
import we can create a Styled Component, good if you have elements that you repeat a lot.
import tw from 'twin.macro';
const MyButton = tw.button`border-2 border-blue-500 px-4 py-2`;
export default function App() {
return (
<MyButton>Hello World!</MyButton>
);
}
And maybe, you want to have a "base" style for a Styled Component, you can Clone and Edit an existing Styled Component.
import tw from 'twin.macro';
const MyButton = tw.button`border-2 border-blue-500 px-4 py-2`;
const MyPrimaryButton = tw(MyButton)`text-white bg-blue-500`; // Cloned Styled Component
export default function App() {
return (
<>
<MyButton>Hello World!</MyButton>
<MyPrimaryButton>My Second Hello World!</MyPrimaryButton>
</>
);
}
Styled Component - Conditional Styles
Maybe you need a conditional style, with styled
import we can do it.
import tw, { styled } from 'twin.macro';
const MyButton = styled.button(({isBold, isPrimary}) => [
tw`mt-5 ml-5 border-2 border-blue-500 px-4 py-2`,
// Ternary
isBold ? tw`font-bold` : tw`font-semibold`,
// Conditional Style
isPrimary && tw`text-white bg-blue-500`
]);
export default function App() {
return (
<MyButton isPrimary>Hello World!</MyButton>
);
}
In this Styled Component, you can create conditionals styles, passing props to the function in this case we have two "isBold" and "isPrimary". We can use the ternary operator to apply certain classes or styles depending on what we need.
Variant Groups
One of twin.macro's new enhancements are the ability to group classes, which I really loved.
Maybe you're working in the Responsive web design or in multiple classes or styles for the hover pseudo-class.
So, twin.macro allows you to group multiple classes, for example you have the following classes in your Styled Component:
<h1 tw="text-blue-500 bg-blue-500 border-2 border-blue-500 hover:text-blue-900 hover:bg-blue-900 hover:border-blue-500" >Hello World</h1>
Maybe you don't want to re-write hover:
prefix to all the classes, now in twin.macro you can do the following:
<h1 tw="text-blue-500 bg-blue-500 hover:(text-blue-900 bg-blue-900)">Hello World</h1>
Do you see it? You only need a single hover:() to add multiple styles that will react to the pseudo-element.
See all variants to Prefix your Classes
Theme
If you have a custom tailwind.config.js file, you can use our custom values of this file with the theme
import available in twin.macro.
twin.macro only uses the
theme
andplugins
variables available in tailwind.config.js
Example
// tailwind.config.js
module.exports = {
theme: {
extend: {
colors: {
electric: '#db00ff',
ribbon: '#0047ff'
}
}
},
plugins: []
}
So, we have our tailwind.config.js with custom variables, to use it, we need to import the theme
in our application.
import tw, { css, theme } from 'twin.macro'
const App = () => (
<div
css={[
tw`flex flex-col items-center justify-center h-screen`,
css({
// Grab values from your config with the theme import
background: `linear-gradient(
${theme`colors.electric`},
${theme`colors.ribbon`}
)`
})
]}
>
<h1>Hello World!</h1>
</div>
)
export default App;
So, as you can see we create a custom linear-gradient using the custom colors that we add to tailwind.config.js. ${theme`color.electric`}
Conclusion
Well, we have it, Twin within our project to take more advantage of using TailwindCSS. If you have anything to add or fix, feel free to let me know in the comments.