Use CSS' `only-child` instead of `if/else` logic

Rails developers are spoiled because the framework automates many of the tedious tasks, minimizing the need for manual coding. Hotwire leveled up the amount of custom JavaScript that is not needed (to be written) anymore.

But CSS has become really powerful too 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 have solved 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).

The vanilla CSS could be written like this:

.li {
  display: none;
}

.li:only-child {
  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).

Pretty cool, right?

This is the first article to highlight CSS features to replace custom logic.

Get UI & Product Engineering Insights for Rails Apps (and product updates!)

Published at . Last updated at . Have suggestions or improvements on this content? Do reach out.

UI components for Ruby on Rails apps

$ 129 one-time
payment

Get Access
  • One-time Payment

  • Access to the Entire Library

  • Built for Ruby on Rails (inc. Rails 8)

  • Designed with Tailwind CSS and Enhanced with Hotwire

  • Updates for 12 months