How to Use Tailwind CSS as a Beginner – Blog | CodeWithBhurtel
Table of contents
How to Use Tailwind CSS as a Beginner
If you have written CSS for any real project, you know the pain. You name a class , then six months later you forget what does, so you create , and slowly your…
If you have written CSS for any real project, you know the pain. You name a class .card, then six months later you forget what .card does, so you create .card-2, and slowly your stylesheet turns into a graveyard of unused rules and specificity wars. Tailwind CSS exists to solve exactly this problem, and it does it in a way that feels strange at first and obvious later. This guide walks you through Tailwind from the very first concept to the patterns professional teams use in production, so by the end you will understand not just how to use it, but why it works the way it does.
What Tailwind CSS Actually Is
Tailwind is a utility-first CSS framework. That phrase sounds abstract, so here is the plain version. Instead of writing custom CSS classes like and defining what that class means in a separate stylesheet, Tailwind gives you small, single-purpose classes that you apply directly in your HTML. One class handles padding. Another handles background color. Another handles font weight. You combine them like building blocks until the element looks the way you want.
<buttonclass="bg-blue-500 text-white px-4 py-2 rounded-md font-semibold">
Click me
</button>
Both produce the same button. The difference is where the styling logic lives. In traditional CSS it lives in a separate file you have to jump back and forth to edit. In Tailwind it lives right next to the element, so you can read the markup and immediately know what it looks like without opening another file.
Why Developers Actually Like This Once They Get Past the Ugly HTML
The first reaction most beginners have is some version of "this looks messy." A button with eight classes does look cluttered compared to one clean class name. But the messiness is a trade. You give up clean-looking HTML and you get back a few things that matter more in real projects.
You stop naming things. Naming is one of the hardest problems in software, and CSS makes you do it constantly. Tailwind removes that tax entirely.
You stop fighting specificity and unused CSS. Every class in Tailwind does one job, so there is no battle between .card .title and .title.featured over which rule wins. And because Tailwind scans your files and only includes the classes you actually used, your final CSS file stays small even as your project grows.
You see the design directly in the markup. When you open a component file, you do not have to guess what it looks like by mentally reconstructing CSS rules from memory. The classes tell you.
Setting Up Tailwind for the First Time
The cleanest way to start, especially if you are learning, is with a framework like Vite or Next.js, since both have first-class Tailwind support.
For a plain Vite project:
npm create vite@latest my-app
cd my-app
npm install tailwindcss @tailwindcss/vite
Then in your main CSS file, usually src/index.css, add a single import:
@import"tailwindcss";
That is the entire setup in modern Tailwind. Older tutorials will show you a tailwind.config.js file with content paths and a longer setup process. Tailwind still supports that, but recent versions default to this simpler import-based flow, so do not be confused if a video from a couple of years ago looks more complicated than what you just did.
If you are using Next.js, running npx create-next-app@latest and choosing "yes" when asked about Tailwind handles the entire setup automatically.
Reading Tailwind Class Names Like a Language
Tailwind classes follow a pattern once you see it. Most classes map directly to a CSS property and value pair, abbreviated.
p-4 means padding of size 4 on all sides. px-4 means padding on the x-axis, left and right. py-2 means padding on the y-axis, top and bottom. m-4, mx-4, and my-2 work the same way for margin.
The numbers are not pixels. They are steps on a spacing scale, where each step equals 0.25rem, which is 4 pixels at the default browser font size. So p-4 is 16 pixels of padding, and p-8 is 32 pixels. This scale exists so your spacing stays consistent across the whole site instead of someone using 13px here and 15px there.
Colors follow a similar pattern. bg-blue-500 sets the background to a medium blue. The number after the color name controls shade, running from 50, which is nearly white, up to 950, which is nearly black. text-blue-500 does the same thing but for text color. border-blue-500 does it for border color.
Once this pattern clicks, you can mostly guess class names correctly. Want larger text? text-lg, text-xl, text-2xl. Want a rounded element? rounded-md, rounded-lg, rounded-full. Want a flex container? flex. Want its children centered? Add items-center justify-center.
Building Your First Real Component
Let's build a simple profile card to see these pieces work together.
Walk through it slowly. max-w-sm caps the card's width so it does not stretch across the whole screen. mx-auto centers it horizontally. bg-white, rounded-xl, and shadow-lg give it the look of a floating card. p-6 adds breathing room inside. The image gets a fixed width and height with w-16 h-16, and rounded-full turns it into a circle. The heading is bold and centered. The button spans the full width of the card with w-full, and hover:bg-indigo-700 darkens it slightly when the user's cursor is over it.
That last part, hover:, is worth pausing on, because it leads into one of Tailwind's most powerful ideas.
State and Responsive Design Through Prefixes
Tailwind handles hover states, focus states, and screen sizes using prefixes attached to the front of a class, rather than separate CSS rules in a separate file.
hover:bg-blue-600 only applies when the mouse hovers over the button. focus:ring-2 only applies when the button is focused, useful for keyboard navigation and accessibility. active:bg-blue-700 applies while the button is being clicked. Each state lives right next to the base style it modifies, so you can see the whole interactive behavior of the button in one line instead of hunting through a stylesheet for :hover and :focus rules.
Responsive design works the same way, using breakpoint prefixes: sm:, md:, lg:, xl:, and 2xl:. Tailwind is mobile-first, meaning a class with no prefix applies to all screen sizes by default, and a prefixed class overrides it starting at that breakpoint and up.
<divclass="text-sm md:text-base lg:text-lg">
This text grows as the screen gets wider.
</div>
On a phone, the text uses text-sm. Once the screen reaches the md breakpoint, around 768px wide, it switches to text-base. Past the lg breakpoint, around 1024px, it becomes text-lg. You never wrote a media query. Tailwind generated it for you behind the scenes.
This is genuinely one of the biggest reasons people stick with Tailwind once they try it. Responsive design in plain CSS means juggling multiple @media blocks scattered across a file. In Tailwind it means reading left to right.
Flexbox and Grid, the Two Layout Tools You Will Use Constantly
Almost every layout on the web today is built with flexbox or grid, and Tailwind gives both full support through simple classes.
flex turns the container into a flex row by default. items-center vertically aligns everything in the middle. justify-between pushes the logo to one side and the links to the other. gap-6 adds spacing between the links without needing margin on each one individually.
This grid stacks into a single column on mobile, then automatically becomes three columns once the screen reaches the md breakpoint. That single line, grid-cols-1 md:grid-cols-3, replaces what would otherwise be a noticeable chunk of custom CSS.
Handling Repetition Without Losing the Benefits
A fair criticism of Tailwind shows up the moment you have the same button style in twenty places across your app. Copying bg-indigo-600 text-white px-4 py-2 rounded-md font-semibold hover:bg-indigo-700 twenty times is not maintainable, and beginners often hit this wall and assume Tailwind does not scale.
The actual solution depends on what framework you are using. If you are working in React, Vue, or any component-based framework, the answer is straightforward: build a Button component once and reuse the component, not the class string.
Now every button in your app references one place. This is the real answer to "doesn't Tailwind cause repetition," and it is why Tailwind pairs so naturally with React, Next.js, and similar frameworks rather than plain static HTML pages.
If you are not using components, Tailwind also supports extracting repeated utility patterns into a custom class using the @apply directive inside your CSS file:
This gives you the readability of a normal class name while still being built entirely from Tailwind's utility system underneath. Most teams reach for components first and save @apply for cases where components are not practical.
Customizing Tailwind to Match Your Brand
Default Tailwind colors and spacing work fine for prototyping, but real products usually need a specific brand identity. Tailwind handles this through theme customization, configured directly in your CSS file in recent versions.
Once defined, you can use these as classes immediately: bg-brand, text-brand, font-display. This means your entire design system, colors, fonts, spacing, and breakpoints, can be controlled from one place, while every component across your app stays in sync automatically.
Dark Mode With Almost No Extra Work
Dark mode is one of those features that takes real effort in plain CSS, since you typically need a second set of color rules guarded behind a media query or a class toggle. Tailwind makes it a prefix, the same pattern as hover and responsive states.
<divclass="bg-white text-black dark:bg-gray-900 dark:text-white">
This adapts to dark mode automatically.
</div>
Add the dark class to your html element, either based on the user's system preference or a manual toggle saved in local storage, and every dark: prefixed utility activates instantly across your whole site.
Performance: Why Your CSS File Stays Small
A common worry is that writing dozens of classes per element must produce a bloated CSS file. The opposite happens. Tailwind scans every file in your project during the build process and generates CSS only for the classes you actually used. An unused utility, no matter how many exist in Tailwind's full library, never makes it into your final stylesheet. Production Tailwind builds are routinely smaller than hand-written CSS for the same project, because there is no leftover dead code from features you removed months ago.
Putting It All Together
Start by getting comfortable with spacing, color, and typography classes, since those cover the majority of everyday styling. Move on to flexbox and grid once basic styling feels natural, since layout is where most of the real design work happens. Learn the hover:, focus:, and responsive prefixes early, because they remove the need for almost all custom CSS and media queries in a typical project. Once you are building anything beyond a single page, lean on components to avoid repetition rather than fighting Tailwind's utility-first nature. And when you are ready to make a project feel like your own product rather than a tutorial, customize your theme so your brand colors and fonts become first-class Tailwind utilities.
Tailwind rewards practice more than memorization. Open the official documentation while you build, look up classes as you need them, and within a few real projects the class names will feel less like a foreign language and more like an extension of how you already think about design.