Creating a simple react component with Tailwind
A simple guide to create reusable ReactJs components with TailwindCSS
Co-authored by Boma George and Mina Tamunowari
Tailwind, unlike its counterparts – Chakra UI and Bootstrap, is a CSS framework that doesn’t provide any predefined component classes for elements; this means it’s as close as possible to writing CSS as you possibly can without actually writing CSS. While other CSS frameworks offer you out-of-the-box component-class elements like alerts, pills, buttons, and input field styling, Tailwind forces you to create everything yourself from scratch. The concept is the foundation with which the framework was created so to use it effectively, you ought to have been very comfortable with the basic to intermediate concepts in CSS.
Furthermore, to achieve this it uses what it calls “utility classes” – predefined class names that represent CSS properties, a concept which draws inspiration from Bootstrap. It allows you to add class names such as “mr-3 ml-4
”, which injects CSS properties into that element automatically such that you get back “margin-right: 3rem; margin-left: 4rem
”.
Now that we have an idea of how Tailwind works, let’s install it and use it in a practice project.
Installing Tailwind
To install Tailwind, run over to their documentation at "tailwind.com/docs".
Create a react project and install tailwind from npm like so:
npm install -D tailwindcss
You can confirm if your installation was successful by going through your package.json file, under devDependencies:
"devDependencies": {
"tailwindcss": "^3.3.2"
}
It shows the name of your package and version.
Then initialize your installation:
npx tailwindcss init
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./src/**/*.{js,jsx,ts,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}
Next, you add these directives to your index.css file for your base CSS file (the parent CSS file which you import other CSS files into):
@tailwind base;
@tailwind components;
@tailwind utilities;
Now you can run your project and use Tailwind utility classes.
Creating a card component
I’ve designed a profile card on Figma to build out of. It consists of an image element which will contain the profile picture, a title, a description section and lastly, a button at the bottom.
<div className="border shadow-black/40 shadow-sm w-96 justify-center items-center p-10 rounded-lg ml-24">
<img
src="https://avatars.githubusercontent.com/u/6916170?v=4"
className="rounded-full w-20 h-20 mb-4"
/>
<h1 className="font-bold text-lg mb-2">Here's a title</h1>
<p className="mb-12">
Here's a description it should be much longer so I'm making it much
longer because it is what it is
</p>
<button className="w-full bg-blue-400 py-3 px-4 rounded-lg text-white text-lg font-bold hover:bg-blue-300">
See more
</button>
</div>
This is a react component so if you’re not using tailwind in a react project you can replace “className
” with “class”.
If you take a close look at the class names, you’ll see some familiarities with CSS such as “border
”, “shadow
”, “justify-center
” etc. Like I said earlier, tailwind injects actual CSS properties and values in place of the class names thus making it easier to write code without switching between multiple CSS files. The Tailwind documentation will help you a lot here in finding the classes you need.
If your utility classes are not working, I’ve written an article to help you troubleshoot your installation here: Troubleshoot Tailwind installation
Converting into a reusable component
Let’s create a reusable card component using our previous code:
export default function UserProfile({ image, title, description }) {
return (
<div className="border shadow-black/40 shadow-sm w-96 justify-center items-center p-10 rounded-lg ml-24">
<img src={image} className="rounded-full w-20 h-20 mb-4" />
<h1 className="font-bold text-lg mb-2">{title}</h1>
<p className="mb-12 ">{description}</p>
<button className="w-full bg-blue-400 py-3 px-4 rounded-lg text-white text-lg font-bold hover:bg-blue-300">
See more
</button>
</div>
);
}
First, you create a file in the components folder and name it “UserProfile
” cut the code into that folder. Finally, take out the dynamic content (title
, description
and image
) and create props for them. Don’t forget to destructure your props.
Next, we add our component into the current page:
import UserProfile from "../components/UserProfile";
export default function TailwindPost() {
return (
<>
<UserProfile image="" title="" description="" />
</>
);
}
This is what our component looks like before we add the content.
Finally, we update the props with content:
<UserProfile
image="https://avatars.githubusercontent.com/u/6916170?v=4"
title="Oladekan Michael"
description="Here's a description it should be much longer so I'm making it much longer because it is what it is"
/>
Our final result:
Consuming a Public API
Let’s take our component further by consuming a free public API from https://randomuser.me/ which allows us to quickly add random users to our card. For this article, we’re going to use Fetch API (Fetch API is a promised-based API interaction tool built into JavaScript. You can read more about it here Consuming API with Fetch API).
import { useEffect, useState } from "react";
import UserProfile from "../components/UserProfile";
export default function TailwindPost() {
const [data, setData] = useState(null);
useEffect(() => {
fetchData();
}, []);
const fetchData = () => {
fetch("https://randomuser.me/api/")
.then((res) => res.json())
.then((data) => setData(data))
.catch((err) => console.log(err));
};
return (
<>
{data &&
data?.results.map((items, i) => (
// Our component
<UserProfile
key={i}
image={items.picture.thumbnail}
title={items.name.first + " " + items.name.last}
description={
"Here's a description it should be much longer so I'm making it much longer because it is what it is"
}
/>
))}
</>
);
}
The result:
Here we’ve been able to extract the profile image and name from the API and added it to our component.
In summary, Tailwind is one of the most customizable CSS frameworks as it is among the closest to actual CSS. Choosing to write CSS this way over using prebuilt-elements-based frameworks is purely a personal choice. The pros and cons begin to get more obvious when it’s being used in a much larger project so think deeply before making a choice.