Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails以外の開発一般

CSS: only-child擬似クラスを使ってif/elseロジックを置き換える技(翻訳)

概要

元サイトの許諾を得て翻訳・公開いたします。

日本語タイトルは内容に即したものにしました。

参考: :only-child - CSS | MDN

CSS: only-child擬似クラスを使ってif/elseロジックを置き換える技(翻訳)

Railsフレームワークは面倒なタスクの多くを自動化して、手書きのコーディングを最小限に抑えられるので、Rails開発者は恵まれています。さらにHotwireのおかげで、カスタムJavaScriptの多くを手書きせずに済むようになりました。

しかし近年のCSSも非常に強力になってきているので、可能な場合はロジックを極力CSSで記述するようにしています。

そんな例のひとつは、「空」のステートを表示する場合です。
たとえばメッセージの受信ボックスが以下のようになっているとしましょう。

このときのHTMLは以下のような感じだとします。

<ul class="divide-y divide-gray-100">
  <li>
    <!-- ここでメッセージのプレビューを表示する -->
  </li>
</ul>

編集部注

上のHTMLは以下のようなERBで生成されているとみなすとよいでしょう。

<ul class="divide-y divide-gray-100">
  <% @messages.each do |message| %>
    <li>
      <!-- ここでメッセージのプレビューを表示する -->
    </li>
  <% end %>
</ul>

従来なら、以下のようにifelse文を書いて場合分けしていたでしょう。

<ul class="divide-y divide-gray-100">
  <li>
    <!-- ここでメッセージのプレビューを表示する -->
  </li>

  <⁠% if @messages.none? %>
    <li>
      <p class="text-base font-normal leading-tight text-center text-gray-400">
        メッセージはありません
      </p>
    </li>
  <⁠% end %>
</ul>

しかしonly-child擬似クラスを使えば、以下のように分岐なしできれいに書けます(なお、ここではTailwind CSSのonlyというユーティリティクラスを使っています)。

<ul class="divide-y divide-gray-100">
  <li>
    <!-- ここでメッセージのプレビューを表示する -->
  </li>

  <li class="hidden only:flex">
    <p class="text-base font-normal leading-tight text-center text-gray-400">
      メッセージはありません
    </p>
  </li>
</ul>

ここで、周りを囲んでいるli要素はデフォルトで非表示になり、そのli要素が「唯一」の要素の場合に限って表示されるようになります(例: display: flex)。

素のCSSで書けば以下のような感じになります。

.li {
  display: none;
}

.li:only-child {
  display: flex;
}

このソリューションの大きなメリットのひとつは、メッセージが(Turbo Streamsで)削除されれば、リスト全体(ul要素)を更新しなくてもこのCSSによる「ロジック」が適用されることです。

とてもクールだと思いませんか?

(本記事は、カスタムロジックを置き換えるCSS機能を紹介する最初の記事です)

関連記事

CSS: 2025年に押さえておきたい最新CSS機能13選(翻訳)

CSS: flexコンテナでは常に`flex-wrap: wrap`を指定しよう(翻訳)


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。