Bootstrap 5 Empty State
An empty state is a UI pattern displayed when a container has no data to show — such as an empty inbox, no search results, or a freshly created account. It is composed from Bootstrap 5 primitives including .card, .d-flex, .flex-column, .align-items-center, .text-center, spacing utilities, and optionally .text-muted and .btn. Use it wherever a blank screen would otherwise leave users confused about whether content is loading, missing, or intentionally absent.
Primary Class
.d-flex .flex-column .align-items-center .text-centerCommon Use Cases
- →A project management app displays an empty state with a 'Create your first project' call-to-action button when a newly registered user has no projects in their dashboard.
- →An e-commerce admin panel shows an illustrated empty state with a prompt to add inventory when the product catalogue table contains zero rows.
- →A support ticket system renders an empty state inside a .card when a filtered search query returns no matching tickets, including a 'Clear filters' button to recover.
- →A social platform shows an empty state in the notifications panel when all alerts have been read, reassuring the user that the absence of items is intentional.
Variants & Classes
| Variant | Description |
|---|---|
| Basic Centred | A minimal vertically and horizontally centred block using flex utilities, suitable for inline panel sections or widget areas. |
| Card Empty State | Wraps the empty state inside a .card with a border, giving it a defined boundary suitable for dashboard widgets or table placeholders. |
| Full-Page Empty State | Occupies the full viewport height using .min-vh-100 and flex utilities, typically used for onboarding flows or zero-data first-run screens. |
| Inline Empty State | A compact horizontal variant that sits inside a table body or list group, keeping the surrounding layout intact without large vertical padding. |
Code Example
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Empty State Example</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css">
<style>
.empty-state-icon {
width: 80px;
height: 80px;
border-radius: 50%;
background-color: var(--bs-secondary-bg);
display: flex;
align-items: center;
justify-content: center;
}
</style>
</head>
<body class="bg-body-tertiary p-4">
<div class="card shadow-sm border-0" style="max-width: 480px; margin: 0 auto;">
<div class="card-body d-flex flex-column align-items-center justify-content-center text-center py-5 px-4">
<!-- Icon container (custom utility class defined above) -->
<div class="empty-state-icon mb-4 text-secondary">
<svg xmlns="http://www.w3.org/2000/svg" width="36" height="36" fill="currentColor" class="bi bi-inbox" viewBox="0 0 16 16">
<path d="M4.98 4a.5.5 0 0 0-.39.188L1.54 8H6a.5.5 0 0 1 .5.5 1.5 1.5 0 0 0 3 0A.5.5 0 0 1 10 8h4.46l-3.05-3.812A.5.5 0 0 0 11.02 4zm-1.17-.437A1.5 1.5 0 0 1 4.98 3h6.04a1.5 1.5 0 0 1 1.17.563l3.7 4.625a.5.5 0 0 1 .1.312V13a1.5 1.5 0 0 1-1.5 1.5h-13A1.5 1.5 0 0 1 .5 13V8.5a.5.5 0 0 1 .1-.312z"/>
</svg>
</div>
<!-- Heading -->
<h5 class="fw-semibold mb-2">Your inbox is empty</h5>
<!-- Supporting text -->
<p class="text-muted mb-4" style="max-width: 300px;">
When you receive messages from your team, they will appear here. Start a conversation to get things moving.
</p>
<!-- Primary action -->
<a href="#" class="btn btn-primary px-4">Start a conversation</a>
<!-- Secondary action -->
<a href="#" class="btn btn-link btn-sm mt-2 text-muted">Learn more about messaging</a>
</div>
</div>
</body>
</html>Live Examples
No Search Results
Shown inside a search results container when a query returns zero matches. Includes a 'Clear search' recovery action composed from .btn and .btn-outline-secondary.
Empty Table State
Placed inside a <tbody> spanning all columns when a data table has no rows to display, keeping the table chrome intact.
First-Run Onboarding Empty State
A full-width card-based empty state for a new user's project list. Uses .card, a large icon area, and a prominent .btn-primary CTA to guide the user to their first action.
Canvas Framework Variants
The Canvas template extends Bootstrap 5 with 1,658+ component variants. Generate any of these using Canvas Builder:
- ✓Card empty state with icon, heading, body text, and primary CTA button
- ✓Full-viewport onboarding empty state with centred layout and two-button group
- ✓Inline table empty state spanning all columns with muted icon and label
- ✓Dark-mode empty state card using bg-dark and text-light utilities
- ✓Canvas Builder can generate any empty state variant automatically from a plain-English prompt
Best Practices
Always include a recovery action
An empty state without a call-to-action leaves users stranded. Include at minimum one .btn that either creates new content or navigates the user somewhere useful. For filtered views, always offer a 'Clear filters' escape hatch as a secondary .btn-link or .btn-outline-* button.
Constrain the content width inside wide containers
Empty states inside full-width .container or .card elements can feel disconnected if the text spans the entire width. Apply an inline style such as max-width: 400px combined with mx-auto on the inner content wrapper to keep the message visually tight and readable on large screens.
Use Bootstrap colour utilities for contextual icons, not custom colours
Stick to .text-primary, .text-secondary, or .text-muted on SVG icons rather than inline fill colours. Combine with .bg-opacity-10 and the matching background utility (e.g. .bg-primary.bg-opacity-10) on a rounded container to create a tinted icon badge without writing any custom CSS beyond the icon circle size.
Avoid images for icons in production empty states
Inline SVG or Bootstrap Icons (via the bi classes with the icon font) are preferable to <img> tags for icon artwork. They scale with colour themes, respect prefers-color-scheme if you wire up Bootstrap's colour modes, and do not require an additional network request.