Tailwind CSS Introduction
Tailwind CSS is a utility-first framework that offers a comprehensive set of low-level utility classes. These classes can be applied directly within HTML or JSX, eliminating the need for writing custom CSS and enable you to build highly flexible and scalable user interfaces with ease.
In CSS, you have to create separate stylesheets, define class names, and manually maintain a growing list of styles. Tailwind eliminates this effort by providing a structured set of utility classes that handle the styling. These utility classes cover a wide range of styling needs, including layout (flex
, grid
, block
), spacing (p-4
, m-2
, gap-6
), typography (text-lg
, font-bold
, leading-relaxed
) and many more.
This means you no longer have to worry about naming conventions, selector specificity, or maintaining massive CSS files. Everything is handled inline, keeping styles modular and easy to manage.
Features of Tailwind CSS
Utility-First Approach
A utility class is a single-purpose CSS class that applies a specific style directly to an element, such as text-center
for centering text or p-4
for adding padding. Instead of writing custom CSS rules in separate stylesheets, developers use these predefined classes to compose styles inline within their HTML or JSX.
<button className="bg-blue-500 text-white px-4 py-2 rounded-md">Click Me</button>
Utility classes in Tailwind CSS follow an atomic design principle, where each class does only one thing. Since each class applies only one style property, there are no unintended side effects when modifying styles. For example, changing the background color of one button does not affect the other as styles are applied directly to the element.
Built-in Responsiveness
Tailwind CSS has a built-in responsive design system to apply styles only on a particular breakpoint. Instead of media queries, it uses responsive variants (sm:
, md:
, lg:
, xl:
, 2xl:
) to adjust styles based on screen size, e.g., md:p-4
, lg:flex-col
, etc. Tailwind also follows a mobile-first approach, where styles apply to the smallest screen by default and are overridden for larger screens.
This eliminates the need for custom media queries. For example, instead of writing:
@media (min-width: 768px) {
.hidden {
display: none;
}
}
You can write the following code to achieve the same behavior:
<div className="md:hidden">Hidden Text</div>
Tailwind’s predefined responsive variants ensure consistency by enforcing a structured design system across all components. This also reduces CSS complexity by eliminating the need for custom media queries, making layouts easier to scale and maintain.
Dark Mode Support
Tailwind CSS provides built-in support for dark mode through the dark:
variant to define both light and dark mode styles within the same element. This built-in functionality allows developers to easily implement dark mode without complex styling overrides, making it a valuable feature for modern applications.
For example, a button might require a default light mode style with background-color: white; color: black;
and then an entirely separate rule for dark mode with background-color: black; color: white;
. This approach results in larger stylesheets, increased specificity conflicts, and a more challenging debugging process. Instead of duplicating CSS properties, bg-white dark:bg-black
can be used to achieve the same effect.
Furthermore, since Tailwind generates only the necessary styles, there’s no risk of shipping unused dark mode CSS, which often occurs in traditional approaches when developers define styles that are not always applied.
No Need for Separate CSS Files
With Tailwind CSS, styles are applied using utility classes directly within markup, eliminating the need for separate external CSS files. This means you don’t need to maintain large CSS files with thousands of lines of custom styles. Instead, all styling logic is contained within the HTML or JSX itself, leading to a more streamlined development process.
You no longer need to switch between multiple files to tweak a component’s appearance. Everything is conveniently contained within the component itself, streamlining collaboration and improving efficiency, particularly in larger projects or teams.
Additionally, Tailwind ensures that only the styles actually used in a project make it into the final CSS bundle, automatically removing all unused styles in production builds. This results in a significantly smaller CSS file compared to traditional approaches, where unused or redundant styles may still be included.
Extensible with Plugins
Tailwind CSS is highly extensible, allowing you to add new utilities and extend variants using plugins. While many customizations—such as adding new spacing values, colors, or responsive variants—can be achieved by extending the theme, plugins enable deeper modifications that go beyond the default capabilities.
For example, a plugin can be used to define new animation utilities. Plugins are particularly useful for standardizing project-specific design patterns or adding missing CSS features. This level of extensibility makes Tailwind CSS a good choice for projects that require advanced customizations while maintaining a consistent and scalable styling system.
Benefits of Tailwind CSS
Rapid Development
Tailwind CSS accelerates development by allowing developers to build interfaces without writing custom CSS. The utility-first approach eliminates the need to switch between HTML and CSS files, keeping all styling within the markup. This not only speeds up prototyping but also enhances efficiency in production environments. By using predefined classes such as p-4
, text-center
, and bg-blue-500
, you can apply styles instantly without creating separate class definitions.
The time-saving aspect extends beyond styling, as teams can maintain uniformity in UI design without additional CSS maintenance. It also reduces onboarding friction for new developers, as they don’t need to learn a custom design system or search through large CSS files for appropriate styles. The simplicity and flexibility of Tailwind makes it ideal for startups and enterprises looking for rapid UI development.
Consistent Design
One of the biggest advantages of Tailwind CSS is its built-in design consistency. Traditional CSS often requires developers to create custom styles, which can lead to inconsistencies across different components. Tailwind solves this problem by enforcing a strict design system with predefined values for spacing, typography, colors, and breakpoints. By using utility classes such as text-lg
, leading-tight
, and tracking-wide
, developers can maintain a uniform look across their entire application.
This approach minimizes design drift and ensures that UI elements remain visually consistent even as the project scales. Tailwind’s @theme
directive also allows you to define custom design tokens, making it easy to create custom themes while maintaining a consistent visual identity.
Improved Maintainability
Maintaining CSS codebases can be challenging, especially in larger projects where styles become tangled over time. Tailwind simplifies maintenance by eliminating the need for custom stylesheets, reducing the risk of conflicting styles and specificity issues. Since styles are applied directly in the markup, developers can easily modify components without searching through multiple CSS files.
This inline styling approach also improves collaboration, as developers can instantly understand and modify styles without needing prior knowledge of the project’s CSS structure. Additionally, the reduced reliance on class name conventions removes the need for enforcing naming standards, leading to cleaner and more maintainable codebases.
Optimized for Performance
Performance optimization is a key benefit of Tailwind CSS. Unlike component libraries that include a large number of unused styles, Tailwind ensures that only the styles used in the project are included in the final CSS file. This results in smaller file sizes and faster page load times.
The reduced file size translates into better Core Web Vitals scores, directly improving metrics such as First Contentful Paint (FCP) and Largest Contentful Paint (LCP), which are critical for user experience and search engine optimization (SEO).
Highly Customizable
While Tailwind CSS provides an extensive set of utility classes by default, it also allows you to create custom styles to match specific design needs. You can modify the default configuration using the @theme
directive to define custom colors, typography, spacing, and more. Instead of being limited to a predefined design language, you have full control over the look and feel of your project, while ensuring consistency.
Tailwind’s plugin ecosystem further enhances its flexibility, enabling you to extend its capabilities with additional utilities and variants. Whether working on a simple web page or a complex enterprise application, Tailwind adapts to your project’s needs without compromising maintainability.
Limitations of Tailwind CSS
Steep Learning Curve
Despite its many advantages, Tailwind CSS presents a steep learning curve for developers who are new to utility-first frameworks. Unlike vanilla CSS, which relies on semantic class names and separate stylesheets, Tailwind requires developers to work with a vast set of utility classes to style elements directly within the markup.
This shift in approach can feel overwhelming at first, particularly for those accustomed to component-based or BEM-style methodologies. The need to remember numerous class names and structure designs without conventional CSS rules may initially slow down development, making the transition challenging for those unfamiliar with utility-driven styling.
Large HTML Files
Since Tailwind applies styles directly within the markup, HTML files can quickly become cluttered with multiple utility classes. This can make the structure harder to read, especially in complex components with extensive styling requirements.
Unlike vanilla CSS, where styles are abstracted into separate stylesheets, Tailwind requires developers to manage styling inline, which some may find challenging for long-term maintainability.
To address this, Tailwind provides directives like @apply
, which allows you to extract commonly used utility patterns into reusable CSS classes. By grouping frequently repeated styles into named classes, @apply
helps maintain a cleaner and more structured codebase while preserving the benefits of Tailwind’s utility-first approach.
Lack of Semantic Class Names
Another common critique of Tailwind CSS is its lack of semantic class names. Traditional CSS encourages the use of descriptive class names that indicate an element's purpose, such as .navbar
or .card-header
, making it easier to understand the structure and intent of the code.
Tailwind’s utility classes focus on styling rather than functionality, describing an element’s appearance rather than its role. This can make it more challenging to infer an element’s purpose at a glance, especially for developers reviewing unfamiliar code.
Why Prefer Tailwind CSS?
Over Vanilla CSS
Prebuilt Classes: Tailwind comes with a comprehensive set of utility classes, reducing the need for repetitive custom CSS. Unlike vanilla CSS, where you write styles from scratch, Tailwind provides predefined classes for layout, spacing, typography, colors, and more. This helps to build UIs faster and maintain consistency across projects without managing multiple CSS files. By using utility classes such as p-4
, text-lg
, bg-blue-500
, etc., you can apply styles directly in the markup.
No More Naming: Unlike vanilla CSS, where you create meaningful and unique class names to avoid conflicts, Tailwind eliminates this requirement by using utility classes. This reduces the overhead of naming conventions. With Tailwind, you can focus on styling rather than coming up with semantic class names. This makes it easier to maintain large projects and collaborate across teams without worrying about conflicting styles.
Rapid Prototyping: By using predefined utility classes, you can quickly build fully responsive and styled interfaces. This approach is particularly beneficial for prototyping, as changes can be made instantly without modifying multiple CSS files. You can experiment with different styles and layouts in real-time, speeding up the design and development process, in turn ensuring that projects move from concept to implementation efficiently.
Smaller CSS Bundle: Tailwind ensures that only the used styles are included in the final CSS bundle. Unlike vanilla CSS frameworks that come with a large, predefined stylesheet, Tailwind generates styles dynamically, removing unused classes and reducing the overall CSS file size. This results in improved performance, faster page loads, and a better user experience, particularly for those on slower connections.
No Specificity Issues: One of the biggest challenges in vanilla CSS is managing specificity conflicts, where styles unintentionally override each other due to complex cascading rules. Since all utilities in Tailwind CSS have the same specificity, conflicts are resolved based on the order of classes in the generated CSS, not by competing specificity rules. This eliminates the need for complex selector hierarchies or !important
overrides, making your code cleaner, more maintainable, and easier to debug.
Built-in Responsiveness: Tailwind includes built-in responsive variants, allowing you to easily create layouts that adapt to different screen sizes. Instead of writing custom media queries, you can use prefixes like sm:
, md:
, lg:
, and xl:
to define styles for different breakpoints. This simplifies the development process and ensures that UIs remain flexible and adaptable across devices, from mobile phones to large desktop screens.
Over Component Libraries
Greater Customization: Tailwind doesn’t impose predefined styles or components. Instead, it provides utility classes to create completely custom designs without being restricted by an existing design system. This makes Tailwind ideal for projects that require unique branding and design flexibility. You can define custom color palettes, typography, and more in Tailwind, ensuring that every aspect of the UI aligns with the project’s design requirements.
Lightweight Output: Unlike component libraries that include a broad set of styles and components (many of which may never be used), Tailwind generates only the necessary styles at build time, resulting in a significantly smaller final CSS file. This enhances page performance by reducing load times and improving overall efficiency. Tailwind ensures that projects remain lightweight and optimized without unnecessary CSS bloat.
No Opinionated Components: Unlike libraries like MUI, which provide pre-styled components that may need to be overridden, Tailwind gives developers full control over their UI components. It does not dictate how buttons, forms, or cards should look, allowing for complete customization. Instead, it allows you to style components from scratch using the utility classes. This flexibility makes Tailwind an excellent choice for teams that want full creative control over their designs without being constrained by predefined styles.
Framework Agnostic: Tailwind CSS is inherently framework-agnostic, meaning it works seamlessly with any JavaScript framework or technology stack. Unlike component libraries that are tied to specific frameworks (e.g., MUI for React, Vuetify for Vue, or Svelte Material UI for Svelte), Tailwind’s utility classes are purely CSS-based and can be used in any project. Whether you're building a static HTML site, a React application, or a server-rendered project with frameworks like Next.js or Laravel, Tailwind integrates effortlessly without imposing framework-specific constraints.
What's New in Tailwind CSS v4?
Feature | Tailwind v4 | Tailwind v3 |
---|---|---|
Performance | Completely overhauled engine; ~3.5x faster full builds and up to 100x faster incremental builds. | Slower build times, requiring more manual configuration. |
Configuration | Configure directly in CSS with | Relies on |
Content Detection | Automatic detection with heuristics;
respects | Requires a content array in |
Import Support | Native | Needed an additional plugin (e.g., |
Color Palette | Modern P3 color palette using OKLCH, offering a broader gamut and more vibrant colors. | Relied on the standard sRGB color space, which is more limited in range. |
Dynamic Utilities | Arbitrary values and custom utilities supported without extra configuration or arbitrary value syntax. | More limited dynamic usage; often required explicit configuration fallback or arbitrary value syntax. |
Build Performance
Tailwind CSS v4.0 introduces a completely overhauled high-performance engine. This update rebuilds the framework from the ground up, incorporating all the insights gained over the years to maximize speed.
v3.4 | v4.0 | Improvement | |
---|---|---|---|
Full build | 378ms | 100ms | 3.78x |
Incremental rebuild with new CSS | 44ms | 5ms | 8.8x |
Incremental rebuild with no new CSS | 35ms | 192µs | 182x |
According to official benchmarks, full rebuilds are now over 3.5 times faster, while incremental builds can achieve speeds more than 8 times faster. The most notable gain occurs with incremental builds that don’t require compiling any new CSS — those are reportedly 100 times faster and finish in just microseconds.
Over extended development, these rapid builds become increasingly common because developers tend to reuse previously utilized classes such as flex
, col-span-2
, or font-bold
.
Configuration
One significant update in Tailwind CSS v4.0 is the move from configuring projects with JavaScript to configuring them directly in CSS. Rather than using a tailwind.config.js
file, all customizations can now be set within the CSS file where Tailwind is imported, eliminating the need for an extra configuration file.
@theme {
colors: {
primary: #1E3A8A;
secondary: #9333EA;
accent: #FACC15;
};
}
This new CSS-first setup offers nearly the same capabilities as tailwind.config.js
, allowing developers to manage design tokens, create custom utilities and variants, and perform other advanced configurations right in the CSS.
Content Detection
In Tailwind CSS v3, it was necessary to maintain a content array to specify which files should be scanned. With version 4.0, new heuristics handle detection automatically, removing the need for that manual configuration.
For example, anything listed in a .gitignore
file is automatically excluded, preventing unnecessary scans of dependencies or generated files that are not tracked in version control, such as:
/node_modules
/coverage
/.next/
/build
All binary file types (images, videos, .zip files, etc.) are ignored by default as well. If a file or directory that is excluded by default needs to be included, the @source
directive can be used directly in the CSS file:
@import "tailwindcss";
@source "../node_modules/@my-company/ui-lib";
This @source
directive uses the same underlying heuristics, so it continues to skip binary file formats and anything else that should be excluded, without requiring explicit extension listings.
Import Support
Before Tailwind CSS v4.0, importing other CSS files inline using @import
required configuring an additional plugin such as postcss-import
. Version 4.0 now includes this functionality by default, removing the need for extra tools:
// postcss.config.js
export default {
plugins: [
"postcss-import",
"@tailwindcss/postcss",
],
};
This import mechanism was developed specifically for Tailwind CSS and is integrated directly into its engine, delivering faster performance due to the tight integration.
Color Palette
Tailwind CSS v4.0 includes a modernized P3 color palette, transitioning from RGB to OKLCH to leverage a broader color gamut and produce more vibrant shades where the sRGB space was previously restrictive.
@theme {
--color-red-50: oklch(0.971 0.013 17.38);
--color-red-100: oklch(0.936 0.032 17.717);
--color-red-200: oklch(0.885 0.062 18.334);
--color-red-300: oklch(0.808 0.114 19.571);
--color-red-400: oklch(0.704 0.191 22.216);
--color-red-500: oklch(0.637 0.237 25.331);
--color-red-600: oklch(0.577 0.245 27.325);
--color-red-700: oklch(0.505 0.213 27.518);
--color-red-800: oklch(0.444 0.177 26.899);
--color-red-900: oklch(0.396 0.141 25.723);
--color-red-950: oklch(0.258 0.092 26.042);
/* ...more default colors*/
Although the entire palette has undergone a refresh, the relative balance among colors is preserved. As a result, even though everything has been updated, upgrading projects from the earlier version should not feel disruptive.
Dynamic Utilities
Tailwind CSS v4.0 simplifies many utilities and variants by allowing specific types of arbitrary values directly—no extra configuration or fallback to arbitrary value syntax is required. For example, it’s now possible to create grids of practically any dimension:
<div className="grid grid-cols-24">
<!-- ... -->
</div>
Likewise, it’s easy to target custom boolean data attributes without defining them upfront:
<div data-active class="opacity-50 data-active:opacity-100">
<!-- ... -->
</div>
Additionally, spacing utilities—like mt-*
, ml-*
, w-*
, or p-*
—are automatically derived from a single spacing variable, enabling them to handle any value by default:
@layer theme {
:root {
--spacing: 0.25rem;
}
}
@layer utilities {
.mt-12 {
margin-top: calc(var(--unit-size) * 12);
}
.ml-20 {
margin-left: calc(var(--unit-size) * 20);
}
.p-5 {
padding: calc(var(--unit-size) * 5);
}
}
Visit the official blog for the complete list of updates in Tailwind v4.
Get Started with Tailwind
Tailwind CDN
Tailwind CSS offers a CDN (Content Delivery Network) version, allowing developers to use the framework instantly without installation or setup. By including a single script tag in an HTML file, you can start using Tailwind’s utility classes right away. This is particularly useful for rapid prototyping, testing, or small projects that don’t require a build process.
To learn how to install Tailwind CDN in your project, visit Tailwind CDN installation guide.
Tailwind CLI
Tailwind CSS provides a CLI (Command Line Interface) tool that allows developers to generate and process Tailwind styles without requiring complex build tools like Webpack or Vite. It offers a lightweight, standalone way to compile Tailwind styles, making it ideal for both simple projects and automated workflows.
To learn how to install Tailwind CLI in your project, visit Tailwind CLI installation guide.
Real World Examples
Product Card Carousel
A horizontal scrolling product card carousel with scroll padding for better product visibility.
export default function ProductCarousel() { const products = [ { id: 1, name: "Wireless Headphones", price: "$299", image: "https://images.unsplash.com/photo-1546435770-a3e426bf472b", alt: "Wireless Headphones" }, { id: 2, name: "Smart Watch", price: "$199", image: "https://images.unsplash.com/photo-1579586337278-3befd40fd17a", alt: "Smart Watch" }, { id: 3, name: "Laptop", price: "$999", image: "https://images.unsplash.com/photo-1496181133206-80ce9b88a853", alt: "Laptop" }, { id: 4, name: "Smartphone", price: "$799", image: "https://images.unsplash.com/photo-1533228100845-08145b01de14", alt: "Smartphone" }, { id: 5, name: "Tablet", price: "$499", image: "https://images.unsplash.com/photo-1527698266440-12104e498b76", alt: "Tablet" }, { id: 6, name: "Camera", price: "$699", image: "https://images.unsplash.com/photo-1502920917128-1aa500764cbd", alt: "Camera" } ]; return ( <div className="scroll-pl-6 scroll-pr-6 snap-x snap-mandatory overflow-x-auto flex gap-6 p-6"> {products.map((product) => ( <div key={product.id} className="snap-center shrink-0 w-72 bg-white rounded-xl shadow-lg" > <img src={product.image} alt={product.alt} className="w-full h-48 object-cover rounded-t-xl" /> <div className="p-4"> <h3 className="text-lg font-semibold">{product.name}</h3> <p className="text-blue-600 font-bold mt-2">{product.price}</p> <button className="w-full mt-4 bg-blue-500 text-white py-2 rounded-lg hover:bg-blue-600"> Add to Cart </button> </div> </div> ))} </div> ); }
Nested Documentation Sidebar
A documentation sidebar menu with elegant hover states and nested submenus that expand to overlay subsequent content.
import React, { useState } from 'react'; export default function DocsSidebar() { const [hoveredItem, setHoveredItem] = useState(null); const sidebarData = [ { id: 'getting-started', title: 'Getting Started', icon: '🚀', subItems: [ { id: 'gs-1', title: 'Quick Start Guide' }, { id: 'gs-2', title: 'Installation' }, { id: 'gs-3', title: 'Basic Configuration' }, { id: 'gs-4', title: 'Project Structure' } ] }, { id: 'components', title: 'Components', icon: '🧩', subItems: [ { id: 'comp-1', title: 'Button' }, { id: 'comp-2', title: 'Input' }, { id: 'comp-3', title: 'Card' }, { id: 'comp-4', title: 'Modal' }, { id: 'comp-5', title: 'Navigation' }, { id: 'comp-6', title: 'Table' } ] }, { id: 'hooks', title: 'Hooks', icon: '🎣', subItems: [ { id: 'hook-1', title: 'useState' }, { id: 'hook-2', title: 'useEffect' }, { id: 'hook-3', title: 'useContext' }, { id: 'hook-4', title: 'useRef' } ] }, { id: 'styling', title: 'Styling', icon: '🎨', subItems: [ { id: 'style-1', title: 'Theme Configuration' }, { id: 'style-2', title: 'Custom Styles' }, { id: 'style-3', title: 'Responsive Design' }, { id: 'style-4', title: 'Dark Mode' } ] }, { id: 'api', title: 'API Reference', icon: '📚', subItems: [ { id: 'api-1', title: 'REST API' }, { id: 'api-2', title: 'GraphQL' }, { id: 'api-3', title: 'WebSocket' }, { id: 'api-4', title: 'Authentication' }, { id: 'api-5', title: 'Error Handling' } ] }, { id: 'deployment', title: 'Deployment', icon: '🚢', subItems: [ { id: 'deploy-1', title: 'Build Process' }, { id: 'deploy-2', title: 'Environment Setup' }, { id: 'deploy-3', title: 'CI/CD Pipeline' } ] } ]; return ( <div className="h-[450px] w-[450px] overflow-hidden bg-gray-50"> <aside className="h-full w-64 overflow-y-auto border-r bg-white"> <div className="p-4"> <h2 className="mb-4 text-lg font-bold text-gray-800">Documentation</h2> <nav className="space-y-1"> {sidebarData.map((section, index) => ( <div key={section.id} className="relative" onMouseEnter={() => setHoveredItem(section.id)} onMouseLeave={() => setHoveredItem(null)} > <button className={`flex w-full items-center rounded-md px-3 py-2 text-sm font-medium transition-colors ${hoveredItem === section.id ? 'bg-blue-50 text-blue-700' : 'text-gray-700 hover:bg-gray-50 hover:text-gray-900' }`} > <span className="mr-2">{section.icon}</span> {section.title} </button> {/* Submenu */} {hoveredItem === section.id && ( <div className="absolute left-0 z-50 mt-0 w-full rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5" style={{ maxHeight: '200px', overflow: 'auto' }} > {section.subItems.map((item) => ( <a key={item.id} href="#" className="block px-4 py-2 text-sm text-gray-700 hover:bg-blue-50 hover:text-blue-700" > {item.title} </a> ))} </div> )} </div> ))} </nav> </div> </aside> </div> ); }
Travel Destination Cards
A set of travel destination cards with a scrollable background that remains fixed while content moves.
export default function TravelDestinations() { const destinations = [ { id: 1, name: "Paris", country: "France", rating: 4.8, src: "https://images.unsplash.com/photo-1502602898657-3e91760cbb34", alt: "Paris cityscape" }, { id: 2, name: "Tokyo", country: "Japan", rating: 4.9, src: "https://images.unsplash.com/photo-1503899036084-c55cdd92da26", alt: "Tokyo street view" }, { id: 3, name: "New York", country: "USA", rating: 4.7, src: "https://images.unsplash.com/photo-1496442226666-8d4d0e62e6e9", alt: "New York skyline" }, { id: 4, name: "Sydney", country: "Australia", rating: 4.6, src: "https://images.unsplash.com/photo-1506973035872-a4ec16b8e8d9", alt: "Sydney opera house" }, { id: 5, name: "Dubai", country: "UAE", rating: 4.8, src: "https://images.unsplash.com/photo-1512453979798-5ea266f8880c", alt: "Dubai skyline" }, { id: 6, name: "Rome", country: "Italy", rating: 4.7, src: "https://images.unsplash.com/photo-1525874684015-58379d421a52", alt: "Rome colosseum" } ]; return ( <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 p-6"> {destinations.map((destination) => ( <div key={destination.id} className="rounded-xl overflow-hidden shadow-lg h-96"> <div className="h-full bg-fixed bg-center bg-cover relative" style={{ backgroundImage: `url(${destination.src})` }} > <div className="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black to-transparent p-6"> <h3 className="text-2xl font-bold text-white">{destination.name}</h3> <p className="text-white mb-2">{destination.country}</p> <div className="flex items-center"> <span className="text-yellow-400">★</span> <span className="text-white ml-1">{destination.rating}</span> </div> </div> </div> </div> ))} </div> ); }
Recipe Card Collection
A collection of recipe cards with varying backdrop saturation effects based on difficulty level.
// RecipeCollection.jsx export default function RecipeCollection() { const recipes = [ { id: 1, name: "Spicy Thai Curry", difficulty: "Hard", time: "45 mins", image: "https://images.unsplash.com/photo-1455619452474-d2be8b1e70cd", alt: "Thai curry dish", chef: "Chef Maria", }, { id: 2, name: "Classic Caesar Salad", difficulty: "Easy", time: "15 mins", image: "https://images.unsplash.com/photo-1551248429-40975aa4de74", alt: "Caesar salad", chef: "Chef John", }, { id: 3, name: "Chocolate Soufflé", difficulty: "Expert", time: "60 mins", image: "https://images.unsplash.com/photo-1606313564200-e75d5e30476c", alt: "Chocolate soufflé", chef: "Chef Pierre", }, { id: 4, name: "Mushroom Risotto", difficulty: "Medium", time: "35 mins", image: "https://images.unsplash.com/photo-1476124369491-e7addf5db371", alt: "Mushroom risotto", chef: "Chef Isabella", }, { id: 5, name: "Sushi Rolls", difficulty: "Hard", time: "50 mins", image: "https://images.unsplash.com/photo-1579871494447-9811cf80d66c", alt: "Sushi rolls", chef: "Chef Tanaka", }, { id: 6, name: "Mediterranean Pasta", difficulty: "Medium", time: "25 mins", image: "https://images.unsplash.com/photo-1473093226795-af9932fe5856", alt: "Mediterranean pasta", chef: "Chef Marco", }, ]; // Dynamically generate backdrop-saturate classes for normal & hover states // e.g. Easy: normal saturate-50 → hover saturate-100, Hard: normal saturate-150 → hover saturate-200 const getSaturationClass = (difficulty) => { switch (difficulty) { case "Easy": return "backdrop-saturate-50 group-hover:backdrop-saturate-100"; case "Medium": return "backdrop-saturate-100 group-hover:backdrop-saturate-150"; case "Hard": return "backdrop-saturate-150 group-hover:backdrop-saturate-200"; case "Expert": return "backdrop-saturate-200 group-hover:backdrop-saturate-[3]"; default: return "backdrop-saturate-100 group-hover:backdrop-saturate-150"; } }; return ( <div className="p-8 bg-gray-100 min-h-screen"> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> {recipes.map((recipe) => ( <div key={recipe.id} // Card container with recipe image as background style={{ backgroundImage: `url(${recipe.image})` }} className=" group relative bg-cover bg-center rounded-xl overflow-hidden shadow-lg h-64 cursor-pointer " > {/* Semi-transparent overlay with backdrop-filter. We use dynamic saturation classes + hover states. */} <div className={` absolute inset-0 z-10 bg-black/40 backdrop-filter transition-all duration-300 ${getSaturationClass(recipe.difficulty)} `} /> {/* The text/content is above the overlay. Using "relative z-20" ensures it's visible on top of the overlay. */} <div className="relative z-20 p-4 text-white drop-shadow-md"> <h3 className="text-xl font-bold mb-2">{recipe.name}</h3> <div className="flex justify-between items-center mb-2"> <span className="text-sm">{recipe.time}</span> <span className={` px-3 py-1 rounded-full text-sm ${ recipe.difficulty === "Easy" ? "bg-green-100 text-green-800" : recipe.difficulty === "Medium" ? "bg-yellow-100 text-yellow-800" : recipe.difficulty === "Hard" ? "bg-orange-100 text-orange-800" : "bg-red-100 text-red-800" } `} > {recipe.difficulty} </span> </div> <p>By {recipe.chef}</p> </div> </div> ))} </div> </div> ); }
Notification Cards
A set of notification cards with different border colors based on their status.
export default function NotificationList() { const notifications = [ { id: 1, title: "System Update", message: "New features have been deployed", status: "info", time: "2 minutes ago" }, { id: 2, title: "Payment Failed", message: "Unable to process payment", status: "error", time: "5 minutes ago" }, { id: 3, title: "Order Shipped", message: "Your order #12345 has been shipped", status: "success", time: "10 minutes ago" }, { id: 4, title: "Low Stock Alert", message: "Product XYZ is running low", status: "warning", time: "15 minutes ago" }, { id: 5, title: "New Comment", message: "John commented on your post", status: "info", time: "20 minutes ago" }, { id: 6, title: "Backup Complete", message: "System backup finished successfully", status: "success", time: "25 minutes ago" } ]; const borderColors = { info: "border-blue-500", error: "border-red-500", success: "border-green-500", warning: "border-yellow-500" }; return ( <div className="space-y-4 p-6"> {notifications.map((notification) => ( <div key={notification.id} className={`p-4 border-l-4 bg-white shadow-sm ${ borderColors[notification.status] }`} > <h3 className="font-bold">{notification.title}</h3> <p className="text-gray-600">{notification.message}</p> <span className="text-sm text-gray-500">{notification.time}</span> </div> ))} </div> ); }
Tailwind Learning Path
To become proficient in Tailwind CSS, follow three key steps: learning, practicing, and applying. Start with the official documentation, which explains the framework’s utility-first approach, configuration options, and available utilities.
Next, practice by experimenting with utility classes in a controlled environment like Tailwind Play. This helps you understand how different classes work, test layouts, and build small UI components without project constraints.
Finally, apply your skills by working on real-world projects where styling decisions impact usability and maintainability. Use platforms like Frontend Mentor, Dev Challenges, and Frontend Practice to build complete UIs and refine your approach to structuring Tailwind styles efficiently.