Empty states with CSS and the `:only-child` selector

On Twitter I came across a great tip on displaying empty states with CSS.

When you're rendering a list, I often wrap a loop in an if/else statement to display an empty state when the list is empty.

<section>
@if($events->isNotEmpty())
@foreach($events as $event)
<article>
{{ $event->name }}
</article>
@endforeach
@else
<p>No events created yet!</p>
@endif
</section>

If you want to reduce nesting and drop the conditional, here's a smart trick with the :only-child selector to display the message when there are no events.

<section>
@foreach($events as $event)
<article>
{{ $event->name }}
</article>
@endforeach
<p>
No events created yet!
</p>
</section>
section > p {
display: none;
}
 
section > p:only-child {
display: block;
}

We hide the message, but when it's the only child in the section, we'll display it. Since there are no other children, we know there are no events.

Using Tailwind

Using Tailwind, we can use the only: variant to do the same.

<section>
@foreach($events as $event)
<article>
{{ $event->name }}
</article>
@endforeach
<p class="hidden only:block">
No events created yet!
</p>
</section>

PS: Extra goodie for Laravel devs: another way to do this is with the lesser-known @forelse Blade directive.

<section>
@forelse($events as $event)
<article>
{{ $event->name }}
</article>
@empty
<p class="hidden only:block">
No events created yet!
</p>
@endforelse
</section>