Combining Components in a UI
Assemble buttons, cards, and badges together into a product listing or dashboard widget to practice component composition.
Combining Components in a UI is a free Tailwind CSS Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Tailwind CSS Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Why Component Composition Matters
Component composition is the practice of assembling small, focused UI pieces — buttons, cards, badges — into larger, functional interfaces. A single well-built card is useful, but a product listing page that combines cards, buttons, badges, and a grid layout is what users actually see and interact with.
Tailwind makes composition natural because all components share the same utility vocabulary. There is no style encapsulation to break — classes from different components never conflict.
Product Card With All Three Components
A product listing card is the perfect showcase for combining buttons, cards, and badges together. The card provides the surface and layout; a badge in the top corner labels the item as Sale or New; and a primary button in the footer drives the purchase action.
This three-component composition is one of the most common patterns in e-commerce and SaaS product UIs.
<div class="relative bg-white rounded-xl shadow-md overflow-hidden max-w-xs">
<!-- Sale badge -->
<span class="absolute top-3 left-3 z-10 px-2 py-0.5 rounded-full text-xs font-bold bg-red-500 text-white">SALE</span>
<!-- Product image -->
<img src="product.jpg" alt="Product" class="w-full h-48 object-cover" />
<!-- Card body -->
<div class="p-5">
<h3 class="text-base font-bold text-gray-900">Wireless Headphones</h3>
<div class="mt-1 flex items-center gap-2">
<span class="text-lg font-bold text-gray-900">$49.99</span>
<span class="text-sm line-through text-gray-400">$79.99</span>
</div>
</div>
<!-- Card footer with button -->
<div class="px-5 pb-5">
<button class="w-full py-2 bg-blue-600 text-white font-semibold rounded-lg hover:bg-blue-700 transition-colors">
Add to Cart
</button>
</div>
</div>Product Listing Grid Layout
Wrap multiple product cards in a responsive grid to build a full listing page. Use grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6 so the layout adapts from a single column on phones to four columns on large screens.
Add a page title and a filter bar above the grid using flex items-center justify-between mb-6 to create a professional-looking listing header.
<div class="max-w-7xl mx-auto px-4 py-8">
<!-- Page header -->
<div class="flex items-center justify-between mb-6">
<h1 class="text-2xl font-bold text-gray-900">Featured Products</h1>
<span class="text-sm text-gray-500">24 items</span>
</div>
<!-- Product grid -->
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
<!-- Cards go here -->
</div>
</div>Dashboard Widget Combining Components
A dashboard widget is another great composition target. Build a card surface that holds a stat number, a colored trend badge, and a text-only action button in the footer.
The badge communicates whether the metric is up or down, the number tells the value, and the button links to a detail view — three distinct components working together as one coherent widget.
<div class="bg-white rounded-xl shadow-md p-5">
<div class="flex items-center justify-between">
<p class="text-sm font-medium text-gray-500">Monthly Revenue</p>
<span class="px-2 py-0.5 rounded-full text-xs font-semibold bg-green-100 text-green-800">
+12.5%
</span>
</div>
<p class="mt-3 text-3xl font-bold text-gray-900">$24,890</p>
<div class="mt-4 border-t border-gray-100 pt-4">
<button class="text-sm font-semibold text-blue-600 hover:text-blue-700">View full report →</button>
</div>
</div>User Table Row With Badges and Buttons
In a data table, each row often combines a user avatar, a name, a status badge, and action buttons — all within a single horizontal row. Use flex items-center gap-3 for the left side and flex gap-2 for the action buttons on the right.
This pattern appears in admin panels, CRM dashboards, and any management interface where multiple records need to be scanned quickly.
<div class="flex items-center justify-between px-4 py-3 bg-white border-b border-gray-100">
<!-- User info -->
<div class="flex items-center gap-3">
<img src="avatar.jpg" alt="" class="w-8 h-8 rounded-full object-cover" />
<div>
<p class="text-sm font-semibold text-gray-900">Sarah Mitchell</p>
<p class="text-xs text-gray-400">sarah@example.com</p>
</div>
</div>
<!-- Status badge -->
<span class="px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800">Active</span>
<!-- Actions -->
<div class="flex gap-2">
<button class="px-3 py-1 text-xs font-medium text-gray-700 border border-gray-300 rounded-md hover:bg-gray-50">
Edit
</button>
<button class="px-3 py-1 text-xs font-medium text-white bg-red-600 rounded-md hover:bg-red-700">
Remove
</button>
</div>
</div>Notification Feed Composition
A notification feed composes avatar images, time-stamp badges, and dismiss buttons into a scrollable list. Wrap each notification in a flex gap-3 p-4 container, add a rounded-full icon background on the left, and close the row with a dismiss button on the far right.
Use divide-y divide-gray-100 on the list wrapper to add automatic border lines between items without adding border classes to each element.
<div class="bg-white rounded-xl shadow-md divide-y divide-gray-100">
<div class="flex gap-3 p-4">
<div class="flex-shrink-0 w-9 h-9 rounded-full bg-blue-100 flex items-center justify-center">
<svg class="w-4 h-4 text-blue-600" fill="currentColor" viewBox="0 0 20 20">
<path d="M10 12a2 2 0 100-4 2 2 0 000 4z"/>
<path fill-rule="evenodd" d="M.458 10C1.732 5.943 5.522 3 10 3s8.268 2.943 9.542 7c-1.274 4.057-5.064 7-9.542 7S1.732 14.057.458 10zM14 10a4 4 0 11-8 0 4 4 0 018 0z" clip-rule="evenodd"/>
</svg>
</div>
<div class="flex-1 min-w-0">
<p class="text-sm text-gray-700"><strong>John</strong> viewed your profile.</p>
<p class="text-xs text-gray-400 mt-0.5">2 minutes ago</p>
</div>
<button class="flex-shrink-0 text-gray-400 hover:text-gray-600">×</button>
</div>
</div>Pricing Card With Feature List
A pricing card combines a card shell, a highlighted badge (for the recommended plan), a price display, a feature list, and a CTA button — making it one of the richest component compositions in UI design.
Use ring-2 ring-blue-600 on the recommended plan's card to highlight it without adding extra margin or padding that would disrupt the grid alignment.
<div class="bg-white rounded-xl shadow-md ring-2 ring-blue-600 p-6">
<div class="flex justify-between items-start">
<h3 class="text-lg font-bold text-gray-900">Pro Plan</h3>
<span class="px-2.5 py-0.5 rounded-full text-xs font-bold bg-blue-600 text-white">Popular</span>
</div>
<p class="mt-4 text-4xl font-bold text-gray-900">$29<span class="text-base font-normal text-gray-500">/mo</span></p>
<ul class="mt-6 space-y-3">
<li class="flex items-center gap-2 text-sm text-gray-600">
<svg class="w-4 h-4 text-green-500" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/></svg>
Unlimited projects
</li>
<li class="flex items-center gap-2 text-sm text-gray-600">
<svg class="w-4 h-4 text-green-500" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/></svg>
Priority support
</li>
</ul>
<button class="mt-6 w-full py-2.5 bg-blue-600 text-white font-semibold rounded-lg hover:bg-blue-700 transition-colors">
Get Started
</button>
</div>Empty State With Button
An empty state is shown when a list or grid has no items. It combines an illustration or icon, a heading, a description, and a call-to-action button — all centered in the available space.
Use text-center py-16 on the container, a large icon wrapped in a colored circle, and a primary button to guide users to the next action. This is a small but important composition that significantly improves UX.
<div class="text-center py-16">
<div class="mx-auto w-16 h-16 rounded-full bg-gray-100 flex items-center justify-center">
<svg class="w-8 h-8 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"
d="M20 13V6a2 2 0 00-2-2H6a2 2 0 00-2 2v7m16 0v5a2 2 0 01-2 2H6a2 2 0 01-2-2v-5m16 0h-2.586a1 1 0 00-.707.293l-2.414 2.414a1 1 0 01-.707.293h-3.172a1 1 0 01-.707-.293l-2.414-2.414A1 1 0 006.586 13H4"/>
</svg>
</div>
<h3 class="mt-4 text-base font-semibold text-gray-900">No products yet</h3>
<p class="mt-1 text-sm text-gray-500">Get started by adding your first product.</p>
<button class="mt-6 px-4 py-2 bg-blue-600 text-white font-semibold rounded-lg hover:bg-blue-700">
Add Product
</button>
</div>Alert Banner With Icon and Button
An alert banner combines a colored background, a status icon, a message, and an optional dismiss button. Use flex items-start gap-3 p-4 rounded-lg for the layout and background utilities like bg-yellow-50 border border-yellow-200 for the warning variant.
The dismiss button on the right uses ml-auto flex-shrink-0 to push itself to the far end of the flex row regardless of message length.
<div class="flex items-start gap-3 p-4 rounded-lg bg-yellow-50 border border-yellow-200">
<svg class="flex-shrink-0 w-5 h-5 text-yellow-500 mt-0.5" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z" clip-rule="evenodd"/>
</svg>
<p class="flex-1 text-sm text-yellow-800">
Your free trial ends in <strong>3 days</strong>. Upgrade to keep access.
</p>
<button class="ml-auto flex-shrink-0 px-3 py-1 text-xs font-semibold text-yellow-800 border border-yellow-400 rounded-md hover:bg-yellow-100">
Upgrade
</button>
</div>Spacing and Alignment Best Practices
When assembling composed UIs, consistent spacing is what separates a polished design from a scattered one. Follow these rules: use gap-* inside flex and grid containers instead of individual margins; use space-y-* for vertical stacks; and reserve p-* for internal padding within component surfaces.
Keep spacing values on the Tailwind scale (multiples of 4px). Avoid mixing arbitrary values with scale values — choose one approach per component and stick to it.
<!-- Use gap inside flex/grid containers -->
<div class="flex gap-4">
<button class="px-4 py-2 bg-blue-600 text-white rounded-lg">Save</button>
<button class="px-4 py-2 border border-gray-300 text-gray-700 rounded-lg">Cancel</button>
</div>
<!-- Use space-y for stacked components -->
<div class="space-y-4">
<div class="bg-white rounded-xl shadow-md p-5">Widget 1</div>
<div class="bg-white rounded-xl shadow-md p-5">Widget 2</div>
<div class="bg-white rounded-xl shadow-md p-5">Widget 3</div>
</div>Quick Check
Test your understanding of Tailwind CSS Mastery concepts from this lesson.
Lesson Recap
In this lesson you learned: product cards combine the card shell with status badges and CTA buttons into a single cohesive component; dashboard widgets and data table rows layer multiple components horizontally within flex containers; and spacing best practices use gap-* inside flex/grid and space-y-* for vertical stacks to keep compositions consistent. Next up we build a responsive navbar.
Frequently asked questions
Is the “Combining Components in a UI” lesson free?
Yes — the full text of “Combining Components in a UI” is free to read here on the web, and the Tailwind CSS Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Tailwind CSS Academy course, upgrade to CoddyKit PRO.
What will I learn in “Combining Components in a UI”?
Assemble buttons, cards, and badges together into a product listing or dashboard widget to practice component composition. You practise Tailwind CSS Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Tailwind CSS Academy?
No prior experience is required. Tailwind CSS Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Combining Components in a UI” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Tailwind CSS Academy lesson?
Yes. Every Tailwind CSS Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Button Variants and States
- Card Component Patterns
- Badge and Tag Components
- Combining Components in a UI