This article was originally published on Rails Designer
Rails developers are spoiled when talking about not needing to write code. Lots of the tedious things are done for you. Hotwire leveled up the amount of custom JavaScript that is not needed (to be written).
But CSS has become really powerful to over the past years. Whenever I can I try to use CSS to do the logic for me.
One of those situations is empty states. For example, a messages inbox:
The HTML looks something like this:
<ul class="divide-y divide-gray-100"> <li> <!-- Message preview here --> </li>
</ul>
Now previously you might solve this with a if/else
statement:
<ul class="divide-y divide-gray-100"> <li> <!-- Message preview here --> </li> <% if @messages.none? %> <li> <p class="text-base font-normal leading-tight text-center text-gray-400"> No messages yet </p> </li> <% end %>
</ul>
But with the only-child
pseudo-class (I am using Tailwind CSS’ only
utility class here, you can write it like so:
<ul class="divide-y divide-gray-100"> <li> <!-- Message preview here --> </li> <li class="hidden only:flex"> <p class="text-base font-normal leading-tight text-center text-gray-400"> No messages yet </p> </li>
</ul>
Here the (wrapping) li-element is hidden (display: none;
) by default and only(!) if it’s the only element display it (eg. display: flex
).
One big upside of this solution, is that if you remove the messages via Turbo Streams, the “logic” is automatically applied without needing to update the complete list (ul-element) for the logic to kick in.
Pretty cool, right?
This is the first article in a collection of Selector Logic