Tables & Lists
Tables & Lists in Tailwind CSS
Tailwind provides comprehensive utilities for styling tables and lists. From controlling table layouts and borders to customizing list markers, these utilities help create clean, readable data presentations and structured content.
Semantic HTML First
Always use proper semantic HTML for tables (<table>, <thead>, <tbody>, <tr>, <th>, <td>) and lists (<ul>, <ol>, <li>) before applying Tailwind classes. Proper semantics ensure accessibility and SEO benefits.
Table Display Utilities
Control table rendering behavior with display utilities that determine how the browser calculates column widths.
Table Layout Utilities
<!-- Auto layout: columns width based on content -->
<table class="table-auto w-full">
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Role</th>
</tr>
</thead>
<tbody>
<tr>
<td>John Doe</td>
<td>john@example.com</td>
<td>Admin</td>
</tr>
</tbody>
</table>
<!-- Fixed layout: equal column widths, faster rendering -->
<table class="table-fixed w-full">
<thead>
<tr>
<th class="w-1/3">Name</th>
<th class="w-1/3">Email</th>
<th class="w-1/3">Role</th>
</tr>
</thead>
<tbody>
<tr>
<td>John Doe</td>
<td>john@example.com</td>
<td>Admin</td>
</tr>
</tbody>
</table>
Table Layout Choice
Use table-auto when content length varies significantly (like user-generated content). Use table-fixed when you want predictable column widths and faster rendering. With table-fixed, you must set widths explicitly or they'll be equal.
Border Collapse and Spacing
Control how table borders render and the spacing between table cells.
Border Collapse Utilities
<!-- Collapsed borders: adjacent borders merge into one -->
<table class="border-collapse border border-gray-300 w-full">
<thead>
<tr>
<th class="border border-gray-300 px-4 py-2">Header 1</th>
<th class="border border-gray-300 px-4 py-2">Header 2</th>
</tr>
</thead>
<tbody>
<tr>
<td class="border border-gray-300 px-4 py-2">Cell 1</td>
<td class="border border-gray-300 px-4 py-2">Cell 2</td>
</tr>
</tbody>
</table>
<!-- Separate borders: space between cells -->
<table class="border-separate border-spacing-2 w-full">
<thead>
<tr>
<th class="border border-gray-300 px-4 py-2 bg-gray-100">Header 1</th>
<th class="border border-gray-300 px-4 py-2 bg-gray-100">Header 2</th>
</tr>
</thead>
<tbody>
<tr>
<td class="border border-gray-300 px-4 py-2 bg-white">Cell 1</td>
<td class="border border-gray-300 px-4 py-2 bg-white">Cell 2</td>
</tr>
</tbody>
</table>
Border Spacing Utilities
<!-- Equal spacing in all directions -->
<table class="border-separate border-spacing-0">No spacing</table>
<table class="border-separate border-spacing-1">0.25rem spacing</table>
<table class="border-separate border-spacing-2">0.5rem spacing</table>
<table class="border-separate border-spacing-4">1rem spacing</table>
<table class="border-separate border-spacing-8">2rem spacing</table>
<!-- Different horizontal and vertical spacing -->
<table class="border-separate border-spacing-x-2 border-spacing-y-4">
<!-- 0.5rem horizontal, 1rem vertical spacing -->
</table>
<!-- Only horizontal spacing -->
<table class="border-separate border-spacing-x-4 border-spacing-y-0">
<!-- 1rem between columns only -->
</table>
Complete Table Examples
Modern Data Table with Stripes
<div class="overflow-x-auto">
<table class="table-auto w-full border-collapse">
<thead>
<tr class="bg-gray-100">
<th class="px-6 py-3 text-left text-xs font-medium
text-gray-700 uppercase tracking-wider">
Name
</th>
<th class="px-6 py-3 text-left text-xs font-medium
text-gray-700 uppercase tracking-wider">
Email
</th>
<th class="px-6 py-3 text-left text-xs font-medium
text-gray-700 uppercase tracking-wider">
Role
</th>
<th class="px-6 py-3 text-left text-xs font-medium
text-gray-700 uppercase tracking-wider">
Status
</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200">
<tr class="hover:bg-gray-50">
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm font-medium text-gray-900">John Doe</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm text-gray-500">john@example.com</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm text-gray-900">Admin</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<span class="px-2 inline-flex text-xs leading-5 font-semibold
rounded-full bg-green-100 text-green-800">
Active
</span>
</td>
</tr>
<tr class="hover:bg-gray-50">
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm font-medium text-gray-900">Jane Smith</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm text-gray-500">jane@example.com</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm text-gray-900">User</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<span class="px-2 inline-flex text-xs leading-5 font-semibold
rounded-full bg-red-100 text-red-800">
Inactive
</span>
</td>
</tr>
</tbody>
</table>
</div>
Card-Style Table
<div class="bg-white rounded-lg shadow overflow-hidden">
<table class="table-auto w-full">
<thead class="bg-gray-800 text-white">
<tr>
<th class="px-6 py-4 text-left text-sm font-semibold">Product</th>
<th class="px-6 py-4 text-left text-sm font-semibold">Price</th>
<th class="px-6 py-4 text-left text-sm font-semibold">Stock</th>
<th class="px-6 py-4 text-right text-sm font-semibold">Actions</th>
</tr>
</thead>
<tbody>
<tr class="border-b border-gray-200 hover:bg-gray-50">
<td class="px-6 py-4">
<div class="flex items-center">
<img src="product.jpg" class="w-10 h-10 rounded-lg mr-3" alt="Product">
<span class="font-medium">Product Name</span>
</div>
</td>
<td class="px-6 py-4 text-gray-700">$99.00</td>
<td class="px-6 py-4">
<span class="text-green-600 font-medium">In Stock</span>
</td>
<td class="px-6 py-4 text-right">
<button class="text-blue-600 hover:text-blue-800 mr-3">Edit</button>
<button class="text-red-600 hover:text-red-800">Delete</button>
</td>
</tr>
</tbody>
</table>
</div>
Comparison Table with Separate Borders
<table class="table-fixed border-separate border-spacing-2 w-full">
<thead>
<tr>
<th class="w-1/4"></th>
<th class="w-1/4 bg-blue-100 border-2 border-blue-300 rounded-lg px-4 py-3">
<div class="text-lg font-bold text-blue-800">Basic</div>
<div class="text-2xl font-bold text-blue-900 mt-2">$9/mo</div>
</th>
<th class="w-1/4 bg-purple-100 border-2 border-purple-300 rounded-lg px-4 py-3">
<div class="text-lg font-bold text-purple-800">Pro</div>
<div class="text-2xl font-bold text-purple-900 mt-2">$29/mo</div>
</th>
<th class="w-1/4 bg-yellow-100 border-2 border-yellow-300 rounded-lg px-4 py-3">
<div class="text-lg font-bold text-yellow-800">Enterprise</div>
<div class="text-2xl font-bold text-yellow-900 mt-2">$99/mo</div>
</th>
</tr>
</thead>
<tbody>
<tr>
<td class="px-4 py-3 font-medium">Users</td>
<td class="bg-white border border-gray-200 rounded-lg px-4 py-3 text-center">5</td>
<td class="bg-white border border-gray-200 rounded-lg px-4 py-3 text-center">25</td>
<td class="bg-white border border-gray-200 rounded-lg px-4 py-3 text-center">Unlimited</td>
</tr>
<tr>
<td class="px-4 py-3 font-medium">Storage</td>
<td class="bg-white border border-gray-200 rounded-lg px-4 py-3 text-center">10GB</td>
<td class="bg-white border border-gray-200 rounded-lg px-4 py-3 text-center">100GB</td>
<td class="bg-white border border-gray-200 rounded-lg px-4 py-3 text-center">1TB</td>
</tr>
</tbody>
</table>
Caption Position
Table Caption Utilities
<!-- Caption at top (default) -->
<table class="w-full caption-top">
<caption class="text-lg font-bold text-gray-900 mb-3">
Employee Directory
</caption>
<thead>...</thead>
<tbody>...</tbody>
</table>
<!-- Caption at bottom -->
<table class="w-full caption-bottom">
<thead>...</thead>
<tbody>...</tbody>
<caption class="text-sm text-gray-600 mt-3">
Last updated: January 2024
</caption>
</table>
List Style Type
Control the appearance of list markers (bullets, numbers, etc.) with list-style utilities.
List Style Type Utilities
<!-- No markers -->
<ul class="list-none">
<li>Item without bullet</li>
<li>Another item</li>
</ul>
<!-- Disc markers (default for ul) -->
<ul class="list-disc pl-5">
<li>Bullet point</li>
<li>Another bullet</li>
</ul>
<!-- Decimal numbers (default for ol) -->
<ol class="list-decimal pl-5">
<li>First item</li>
<li>Second item</li>
</ol>
<!-- Other list styles -->
<ul class="list-circle pl-5">
<li>Circle marker</li>
</ul>
<ul class="list-square pl-5">
<li>Square marker</li>
</ul>
<ol class="list-lower-alpha pl-5">
<li>a. First item</li>
<li>b. Second item</li>
</ol>
<ol class="list-upper-alpha pl-5">
<li>A. First item</li>
<li>B. Second item</li>
</ol>
<ol class="list-lower-roman pl-5">
<li>i. First item</li>
<li>ii. Second item</li>
</ol>
<ol class="list-upper-roman pl-5">
<li>I. First item</li>
<li>II. Second item</li>
</ol>
List Style Position
List Position Utilities
<!-- Inside: marker inside content box (default) -->
<ul class="list-disc list-inside bg-gray-100 p-4">
<li>Marker is inside the content box</li>
<li>Text wraps under the marker</li>
</ul>
<!-- Outside: marker outside content box -->
<ul class="list-disc list-outside pl-5 bg-gray-100 p-4">
<li>Marker is outside the content box</li>
<li>Text does not wrap under marker</li>
</ul>
Styling List Markers
Custom Marker Colors and Styles
<!-- Colored markers using marker pseudo-element -->
<ul class="list-disc pl-5 space-y-2">
<li class="marker:text-blue-600">Blue marker</li>
<li class="marker:text-red-600">Red marker</li>
<li class="marker:text-green-600">Green marker</li>
</ul>
<!-- Styled markers with size -->
<ul class="list-disc pl-5 space-y-2">
<li class="marker:text-sky-600 marker:text-lg">
Large blue marker
</li>
<li class="marker:text-purple-600 marker:font-bold">
Bold purple marker
</li>
</ul>
<!-- Custom content for markers -->
<ol class="list-none pl-0 space-y-2">
<li class="flex items-start">
<span class="flex-shrink-0 w-6 h-6 rounded-full bg-blue-600
text-white flex items-center justify-center text-sm mr-3">
1
</span>
<span>Custom numbered marker with styling</span>
</li>
<li class="flex items-start">
<span class="flex-shrink-0 w-6 h-6 rounded-full bg-blue-600
text-white flex items-center justify-center text-sm mr-3">
2
</span>
<span>Another custom marker</span>
</li>
</ol>
Complete List Examples
Feature List with Icons
<ul class="space-y-3">
<li class="flex items-start">
<svg class="w-6 h-6 text-green-500 mr-3 flex-shrink-0" fill="currentColor">
<path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"/>
</svg>
<span>High-quality products with lifetime warranty</span>
</li>
<li class="flex items-start">
<svg class="w-6 h-6 text-green-500 mr-3 flex-shrink-0" fill="currentColor">
<path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"/>
</svg>
<span>24/7 customer support</span>
</li>
<li class="flex items-start">
<svg class="w-6 h-6 text-green-500 mr-3 flex-shrink-0" fill="currentColor">
<path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"/>
</svg>
<span>Free shipping on orders over $50</span>
</li>
</ul>
Nested Lists with Different Styles
<ol class="list-decimal pl-5 space-y-2">
<li>
<strong>Getting Started</strong>
<ul class="list-disc pl-5 mt-2 space-y-1">
<li>Create an account</li>
<li>Verify your email</li>
<li>Complete your profile</li>
</ul>
</li>
<li>
<strong>Setting Up</strong>
<ul class="list-disc pl-5 mt-2 space-y-1">
<li>Configure preferences</li>
<li>Connect integrations</li>
<li>Invite team members</li>
</ul>
</li>
<li>
<strong>Advanced Features</strong>
<ul class="list-disc pl-5 mt-2 space-y-1">
<li>Custom workflows</li>
<li>API access</li>
<li>Analytics dashboard</li>
</ul>
</li>
</ol>
Card List (Remove Default Markers)
<ul class="list-none space-y-4">
<li class="bg-white rounded-lg shadow p-6 border-l-4 border-blue-500">
<h3 class="text-xl font-bold text-gray-900 mb-2">Step 1: Plan</h3>
<p class="text-gray-600">
Define your goals and create a detailed project plan.
</p>
</li>
<li class="bg-white rounded-lg shadow p-6 border-l-4 border-green-500">
<h3 class="text-xl font-bold text-gray-900 mb-2">Step 2: Build</h3>
<p class="text-gray-600">
Implement your solution with best practices.
</p>
</li>
<li class="bg-white rounded-lg shadow p-6 border-l-4 border-purple-500">
<h3 class="text-xl font-bold text-gray-900 mb-2">Step 3: Launch</h3>
<p class="text-gray-600">
Deploy and monitor your project in production.
</p>
</li>
</ul>
Accessibility Considerations
When removing list markers with list-none, ensure alternative visual cues exist. Lists convey semantic meaning to screen readers. If styling as cards or removing markers, the underlying HTML should still use proper list elements for accessibility.
Exercise 1: Product Comparison Table
Create a responsive product comparison table:
- 3-4 products with different pricing tiers
- Use
table-fixedlayout with equal column widths - Header row with product names and prices
- Feature rows comparing specifications
- Use checkmarks/crosses for feature availability
- Add hover effects on rows
- Wrap in scrollable container for mobile
Exercise 2: Task List with Custom Markers
Build a task list with custom styled markers:
- Use
list-noneand create custom numbered markers - Each marker: circular badge with number
- Different colors for completed vs. pending tasks
- Include task title, description, and due date
- Add checkboxes for task completion
- Nested subtasks under main tasks
Exercise 3: Data Table with Actions
Create an admin dashboard data table:
- User management table with avatar, name, email, role, status
- Status badges (active/inactive) with appropriate colors
- Action buttons (edit, delete) in last column
- Striped rows (alternating backgrounds)
- Hover effects on rows
- Sortable column headers (show sort icon)
- Responsive: horizontal scroll on mobile
Best Practices for Tables and Lists
- Always wrap tables in containers with
overflow-x-autofor responsive design - Use
whitespace-nowrapto prevent cell text wrapping when needed - Add hover effects to table rows for better interactivity
- Use
divide-yutility for row separators instead of individual borders - Consider
stickypositioning for table headers on long tables - Use proper padding (
px-6 py-4) for comfortable cell spacing - Add
space-yutilities between list items for better readability - Use semantic HTML (<thead>, <tbody>, <th>, <td>) for accessibility
Summary
Tailwind provides comprehensive utilities for tables and lists:
- Table Layout: Control column width calculation (
table-auto,table-fixed) - Border Collapse: Merge or separate cell borders (
border-collapse,border-separate) - Border Spacing: Control spacing between cells (
border-spacing-{n}) - Caption Position: Place table captions (
caption-top,caption-bottom) - List Style Type: Choose marker styles (
list-disc,list-decimal,list-none) - List Position: Control marker placement (
list-inside,list-outside) - Marker Styling: Customize marker appearance (
marker:text-{color})
These utilities enable you to create professional, accessible data tables and structured lists that work beautifully across all devices. Remember to prioritize accessibility by using semantic HTML and providing clear visual hierarchies.