DEV Community

thomasvanholder
thomasvanholder

Posted on

Display content with the 'only' class in Tailwind CSS

With Tailwind's JIT release, developers can act up HTML elements that are in a specific state. The only class is practical addition to display a HTML element if it has no sibling HTML elements. Under the tailwind-hood, the only class translates into the only-child selector.



Empty state

Imagine you want to display content only if it is stored in the database. The initial step is to create a conditional statement to render parts of the HTML based on the condition you provide. In the rails example below, the conditional check is @tasks.empty?. If the @tasks collection is empty, the empty state message is displayed.

<ul>
  <% if @tasks.empty? %>
    <% @tasks.each do |task| %>
      <%= render "task/task", task: task %>
    <% end %>

  <% else %>
    <p class="block">All tasks completed.</p>
  <% end %>
</ul>
Enter fullscreen mode Exit fullscreen mode

only:block

Now, although the code above definitely works, you have added a(nother) conditional to your code.

An alternative is to handle this natively with CSS.

<ul>
  <% @tasks.each do |task| %>
      <%= render "task/task", task: task %>
  <% end %>

  <p class="hidden only:block">All tasks completed.</p>
</ul>
Enter fullscreen mode Exit fullscreen mode

The empty state's element (p-tag) has a default state of hidden. The added only class change the display status to block when the element has no siblings.

Refactored

Or leverage the rails collection renderer to re-factor your code into:

<ul>
  <%= render @tasks %>

  <p class="hidden only:block">All tasks completed.</p>
</ul>
Enter fullscreen mode Exit fullscreen mode

Discussion (1)

Collapse
darkwiiplayer profile image
DarkWiiPlayer • Edited on

sooo... it basically does something along the lines of

hidden { display: none; }
.only\:block:only-child { display: block }
Enter fullscreen mode Exit fullscreen mode

That's certainly useful, but not nearly as much magic as it seems :D


One thought I'd like to add is that this CSS-solution has a few interesting implications.

Say, for example, you wanted the last task in the list to have some special styling. Assuming your tasks are rendered as <div class="task> here goes content </div>, you might write some CSS that looks like this:

.task:last-child {
   color: red;
}
Enter fullscreen mode Exit fullscreen mode

But having that hidden block at the end will mess with this selector. This is yet another reason why :nthlast-child(1 of .task) would be a very helpful addition to CSS.

Another implication is that adding or removing tasks through JavaScript without re-rendering would still eventually show and hide the placeholder, whereas otherwise the JS code would have to take care of adding and removing the element, either by adding it as a template from ruby, or by duplicating the HTML in the JS code.