webdevpuneet.com

Empty State — Free HTML CSS Snippet

Empty State · Layouts · Plain HTML & CSS · Live preview

CategoryLayouts

Copy & paste

Source Code

<div class="scene">
  <div class="empty">
    <div class="illustration">
      <svg width="80" height="80" viewBox="0 0 80 80" fill="none">
        <circle cx="40" cy="40" r="38" fill="#f1f5f9" stroke="#e2e8f0" stroke-width="2"/>
        <rect x="24" y="22" width="32" height="40" rx="4" fill="#fff" stroke="#cbd5e1" stroke-width="1.5"/>
        <rect x="30" y="30" width="20" height="2.5" rx="1.25" fill="#e2e8f0"/>
        <rect x="30" y="36" width="16" height="2.5" rx="1.25" fill="#e2e8f0"/>
        <rect x="30" y="42" width="18" height="2.5" rx="1.25" fill="#e2e8f0"/>
        <circle cx="57" cy="55" r="12" fill="#f8fafc" stroke="#e2e8f0" stroke-width="1.5"/>
        <line x1="53" y1="55" x2="61" y2="55" stroke="#94a3b8" stroke-width="2" stroke-linecap="round"/>
        <line x1="57" y1="51" x2="57" y2="59" stroke="#94a3b8" stroke-width="2" stroke-linecap="round"/>
      </svg>
    </div>
    <h3>No documents yet</h3>
    <p>You haven't created any documents. Start by creating your first one and it will appear here.</p>
    <div class="actions">
      <button class="btn primary" onclick="this.textContent='Creating…';setTimeout(()=>this.textContent='Create document',1500)">
        <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
        Create document
      </button>
      <button class="btn ghost">Import existing</button>
    </div>
    <a href="#" class="learn-link">Learn more about documents →</a>
  </div>
</div>

Extend with AI

Take This Snippet Further With AI

The AI prompt for this one is for Patreon supporters ($3 a month), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.

· Become a supporter

What's included

Features

Centred flex column layout with gap spacing between all elements
Large emoji in a soft-tinted circle illustration
h2 heading + p description for context and reassurance
Primary CTA (filled) + secondary CTA (ghost) button pair
max-width: 360px keeps content compact and readable
Pure HTML and CSS — no JavaScript required
Works in any container — modal, page section, or full screen
Export as HTML file, React JSX, or React + Tailwind CSS
Mobile (375px), Tablet (768px), Desktop device preview buttons
Live split-pane editor — preview updates as you type

About this UI Snippet

Empty State — Centred Illustration, Heading & CTA for Zero-Data Screens

Screenshot of the Empty State snippet rendered live

An empty state is shown when a page section has no data to display — an empty inbox, a search with no results, a new user with no items yet. It is the counterpart to the skeleton loader, which covers the loading phase before data either arrives or comes back empty. Good empty states don't just show nothing — they explain the situation, reassure the user, and provide a clear action to take next.

This snippet implements the standard empty state layout: a large emoji or illustration, a heading, a description, and one or two action buttons.

The layout

.empty uses display: flex; flex-direction: column; align-items: center; gap: 14px; text-align: center — a vertically stacked, centred layout. max-width: 360px keeps the content compact and readable.

The illustration

A large emoji in a soft-tinted circle communicates the context of the empty state at a glance. Replace the emoji with an SVG illustration for a more branded look.

Primary and secondary CTAs

The primary CTA (filled button) is the most likely next action: "Create your first project", "Add an item", "Invite a teammate". The secondary CTA (ghost button) is an alternative: "Browse examples", "Learn more" — use the button group variants for the filled/ghost pairing. Showing two options without overwhelming the user is the standard empty state pattern.

Different empty state types

Three distinct empty state scenarios need different messaging: (1) First use — the user has not created anything yet. Use encouraging language: "Create your first project". (2) Empty search — a search box returned no results. Show what was searched: 'No results for "design"'. (3) No permissions — the user cannot see this content. Explain why and offer an alternative action.

The emoji vs SVG illustration choice

Emoji icons are quick to implement and universally recognised but vary by platform. SVG illustrations are fully branded but require design work. The emoji-in-circle pattern in this snippet is a practical middle ground for most applications. Replace the emoji div with an <img> element pointing to an SVG illustration for production use.

Microcopy guidelines

The heading should be factual and brief: "No projects yet", "Nothing here", "All caught up". The description should explain why and what to do next: "Projects you create will appear here. Start by adding your first one." Avoid technical jargon or system-internal error terminology in empty states that users see regularly.

Placement and sizing

Centre the empty state vertically and horizontally within its container. For dashboard widgets, use a reduced size (smaller emoji, smaller text). For full-page empty states (empty inbox, empty search), use the full-size variant. The max-width: 360px constraint keeps it readable on wide screens without the content stretching too far.

Step by step

How to Use

  1. 1
    Load the snippetClick "Empty State" in the sidebar. The preview shows the centred empty state with illustration, heading, description, and CTA buttons.
  2. 2
    Update the illustrationIn the HTML panel, change the emoji inside .illustration to match your context.
  3. 3
    Update heading and descriptionChange the h2 and p text to explain the empty state context and reassure the user.
  4. 4
    Update CTA labels and actionsChange the primary and secondary button text to the most relevant actions for this empty state.
  5. 5
    Change the illustration colourUpdate the background colour on .illustration in the CSS panel to match your brand.
  6. 6
    Export in your formatClick "HTML" for a standalone file, "JSX" for a React component, or "Tailwind" for a React + Tailwind version.

Real-world uses

Common Use Cases

Empty inbox and notification feed
Show when there are no messages, notifications, or alerts. Reassure the user and offer a path to create content.
No search results state
Show when a search or filter returns zero results. Suggest broadening the search or clearing filters.
New user onboarding state
Show to first-time users with no content yet. The CTA guides them to create their first item.
Dashboard widgets with no data
Use inside chart or metric widgets when no data is available yet. Better than a blank or broken chart.
Error and connection failure states
Adapt for error states: change the emoji to a warning icon, update the heading to "Something went wrong", and show a Retry button.
Filtered list with no matches
Show when applied filters produce no results. The secondary CTA clears all filters and restores the full list.
Related: Link in Bio Page
See the Link in Bio Page for a related layouts pattern worth pairing with this one.

Got questions?

Frequently Asked Questions

A good empty state explains why it is empty (no items yet, no search results), reassures the user (this is normal), and gives them a clear action to take next (create the first item, try a different search). Avoid generic "No data" — that's unhelpful.

Replace the emoji span with an <img src="empty-illustration.svg"> or inline SVG. Set width and height to match the circle size (80px). Remove the background circle styling if the SVG already has its own background.

Change all three text elements: the emoji (to match the type of missing content), the heading ("No invoices yet" vs "No messages"), and the description ("Create your first invoice to get started").

Yes. Remove the min-height: 100vh from the body and set a fixed height on the .empty container. The flex centring works in any container size.

Yes. Click "JSX" for a React component. Pass icon, heading, description, and CTA props. Render conditionally: {items.length === 0 && <EmptyState ... />}.

Add a fadeIn CSS animation to .empty: @keyframes fadeIn { from { opacity: 0; transform: translateY(10px) } to { opacity: 1; transform: translateY(0) } }. The illustration, text, and buttons fade up together.