Getting Started with Tailwind CSS
Initial Setup and Configuration
Install required dependencies:
npm init -y
npm install tailwindcss postcss-cli autoprefixer
npx tailwindcss init
Configure tailwind.config.js:
module.exports = {
content: ["./src/**/*.{html,js}"],
}
Create postcss.config.js:
module.exports = {
plugins: [
require("tailwindcss"),
require("autoprefixer")
]
}
Create styles/tailwind.css:
@tailwind base;
@tailwind components;
@tailwind utilities;
Update package.json scripts:
{
"scripts": {
"build:css": "postcss styles/tailwind.css -o dist/styles/tailwind.css"
}
}
Run the build process:
npm run build:css
Create src/index.html:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Tailwind Demo</title>
<link rel="stylesheet" href="../dist/styles/tailwind.css"/>
</head>
<body>
<h1 class="text-4xl font-bold text-center text-blue-600">Welcome to Tailwind</h1>
</body>
</html>
Utility-First Approach Benefits
Tailwind CSS employs a utility-first methodology that offers several advantages:
- Build custom designs without writing custom CSS
- Avoid inventing class names for every element
- Prevent CSS file bloat
- Make design changes with confidence
Compared to inline styles, Tailwind provides:
- Design constraints and consistency
- Built-in responsive design utilities
- State variants like hover, focus, and active
Responsive Design Implemantation
Apply responsive clases:
<!-- Applies from 640px screen width and up -->
<div class="sm:bg-red-600 h-4"></div>
<!-- Applies between 640px and 768px -->
<div class="sm:max-md:bg-green-600 h-4"></div>
<!-- Custom breakpoint -->
<div class="tablet:bg-blue-600 h-4"></div>
Customize breakpoints in tailwind.config.js:
module.exports = {
theme: {
screens: {
'sm': '640px',
'md': '768px',
'lg': '1024px',
'xl': '1280px',
'2xl': '1536px'
},
extend: {
screens: {
'tablet': '640px',
'laptop': '1024px',
'desktop': '1280px'
}
}
}
}
Pseudo-classes and Pseudo-elements
Basic state variants:
<button class="text-white bg-green-600 hover:bg-red-600">Click Me</button>
List item styling with odd/even:
<ul>
<li class="odd:text-red-600 even:text-green-600">Item 1</li>
<li class="odd:text-red-600 even:text-green-600">Item 2</li>
</ul>
Form input states:
<label>
<input type="email" class="border border-green-600 focus:outline-none invalid:border-red-600"/>
</label>
Group hover effects:
<div class="w-48 border border-red-600 group">
<div class="w-24 h-8 border border-green-600 group-hover:bg-green-600"></div>
</div>
Peer sibling styling:
<label>
<input type="text" class="peer focus:outline-none border"/>
<span class="peer-focus:text-green-600">Focus indicator</span>
</label>
Pseudo-eleemnts:
<div class="before:content-['Hello'] after:block after:h-8 after:bg-green-600"></div>
Custom modifiers with arbitrary values:
<div class="w-48 border border-red-600 [&:hover_div]:bg-green-600">
<div class="w-24 h-8 border border-green-600"></div>
</div>
Custom variant plugin:
const plugin = require('tailwindcss/plugin')
module.exports = {
plugins: [
plugin(function ({addVariant}) {
addVariant('hover-descendants', '&:hover div')
})
],
}
Reusable Component Styles
Add watch script to package.json:
{
"scripts": {
"watch:css": "postcss styles/tailwind.css -o dist/styles/tailwind.css --watch"
}
}
Define component classes in styles/tailwind.css:
@layer components {
.btn-primary {
@apply py-1 px-2 bg-blue-600 text-white rounded-lg shadow-md hover:bg-blue-800 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-opacity-75;
}
.btn-success {
@apply py-1 px-2 bg-green-600 text-white rounded-lg shadow-md hover:bg-green-800 focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-opacity-75;
}
}
Usage in HTML:
<button class="btn-primary">Primary Button</button>
<button class="btn-success">Success Button</button>
Theme Customization
Generate full configuration:
npx tailwindcss init tailwind-full.config.js --full
Extend theme with plugins:
const plugin = require('tailwindcss/plugin')
module.exports = {
content: ["./src/**/*.{html,js}"],
theme: {
extend: {},
},
plugins: [
plugin(function ({addBase, addComponents, addUtilities, theme}) {
addBase({
'#app': {
overflow: 'auto'
}
})
addComponents({
'.btn-danger': {
color: 'white',
'font-size': theme('fontSize.sm[0]'),
'line-height': theme('fontSize.sm[1].lineHeight'),
background: theme('colors.red.600'),
padding: `${theme('space.1')} ${theme('space.2')}`,
'border-radius': theme('borderRadius.DEFAULT')
},
'.btn-danger:hover': {
background: theme('colors.red.800')
}
})
addUtilities({
'.text-truncate': {
'white-space': 'nowrap',
overflow: 'hidden',
'text-overflow': 'ellipsis'
}
})
})
],
}
Enhanced styles/tailwind.css with customizations:
@tailwind base;
@tailwind components;
.btn-custom {
color: white;
font-size: theme('fontSize.sm[0]');
line-height: theme('fontSize.sm[1].lineHeight');
background: theme('colors.blue.600');
padding: theme('space.1') theme('space.2');
border-radius: theme('borderRadius.DEFAULT');
}
.btn-custom:hover {
background: theme('colors.blue.800');
}
@tailwind utilities;
@layer base {
html, body, #app {
height: 100%;
}
}
@layer components {
.btn-component {
@apply px-2 py-1 text-white text-sm rounded bg-green-600 hover:bg-green-800
}
}
@layer utilities {
.clearfix-after {
@apply after:block after:clear-both
}
}
Implementation with arbitrary values:
<div id="app">
<style>
:root {
--custom-primary: #3b82f6;
--custom-font-size: 32px;
}
</style>
<div class="h-[32px] bg-[--custom-primary] w-[theme(spacing.40)]"></div>
<div class="[border:16px_solid_var(--custom-primary)] before:content-['custom\_content']"></div>
<div class="text-[length:--custom-font-size] text-[color:--custom-primary]">Styled Text</div>
<div class="clearfix-after border">
<button class="btn-custom float-left">Custom Button</button>
<button class="btn-component float-left">Component Button</button>
<button class="btn-danger float-left">Plugin Button</button>
</div>
<div class="text-truncate w-24">This text will be truncated when too long</div>
</div>
Additional Configuration Options
Custom configuration file:
@config "./tailwind.custom.config.js";
@tailwind base;
@tailwind components;
@tailwind utilities;
Prefix configuration:
module.exports = {
prefix: 'tw-',
}