🫧

Tailwind CSS ✖️ data属性 スタイルの動的変更をスッキリ書きたい🛁

2023/06/22に公開

はじめに

tailwindを数ヶ月使ってみました。
・jsファイルにそのまま書ける
・クラス名を考えなくていい
・デザインシステムとしても機能する
等々、個人的には大きく恩恵を感じています。

対して難点といえば、
やはり記述が長くなって見辛くなりやすいところでしょうか。
そこで、少しでも綺麗なコードになるのでは!というカスタマイズをご紹介します。

条件付きのスタイル適用

tailwindの記述方法でdata属性に基づいた条件でスタイルの切り替えがあります。

data属性とは

HTML5 (en-US) は、特定の要素に関連付ける必要があるが、定義済みの意味を持つ必要のないデータに対する拡張性を念頭に置いて設計されています。 data-* 属性により、標準外の属性やDOM の追加プロパティなどの特殊な方法に頼らずに、標準的な意味のある HTML 要素に追加情報を格納することができます。
https://developer.mozilla.org/ja/docs/Learn/HTML/Howto/Use_data_attributes

通常だとクラス名の中に条件分岐を記述することになるかと思います。

<input className={errors != null ? 'border-red' : '' } />

data属性を使用すると、下記のように判定ロジックとスタイル設定を切り離すことができます!
(疑似要素・擬似クラスなどと同様の記述方法ですね。)

<input data-error={errors != null} className="data-error:border-red" />

書き方

パターン① 直接条件式を記述

https://tailwindcss.com/docs/hover-focus-and-other-states#data-attributes

  • 任意のdata属性を設定
  • クラス名にdata-[条件]:スタイルを記述
// bg-blueが適用される
 <button data-color="blue" className="bg-red data-[color=blue]:bg-blue">
    push
 </button>
 
 // 条件がfalseの場合、もしくは指定なしの場合、bg-blueは適用されない
  <button data-color="red" className="bg-red data-[color=blue]:bg-blue">
    push
 </button>
 
 <button className="bg-red data-[color=blue]:bg-blue">
    push
 </button>

パターン② data属性のセレクターを作成

上記のようにclassNameに直接条件式を記述することもできますが、
エラー時のスタイル変更など汎用的な条件がある場合は、ショートカットを作成すると便利です。

例えば、data-errorというdata属性のセレクターを作成してみます。

tailwind.config.jsの設定

  • theme.dataセクションにerrorを作成
tailwind.config.js
module.exports = {
  theme: {
    data: {
       error: 'error=true'
    },
  },
}

使用箇所

  • クラス名にdata-error:スタイルを記述
// data-error属性がtrueの時、data-error:*のスタイルが適用される
<input data-error={errors != null} className="data-error:border-red data-error:text-red " />

さらにまとめる

@applydata属性適用時のスタイルをまとめると、さらにすっきりしますね✨

@tailwind components;
@layer components {
    .error {
        @apply font-semibold text-red border-red ;
    }
}
<input data-error={errors != null} className="data-error:error" />

ここでは詳細は省きますが、group-*area-*なんかも同じ感覚で使えます!

組み合わせ

擬似要素・擬似クラスや別のdata属性同士の組み合わせでもできます。(AND条件で判定されます)

// data-sundayがtrue、かつdata-currentMonthがtrueのとき、bg-pinkが適用される
<div
    data-sunday={weekday === 0}
    data-currentMonth={month === currntMonth}
    className="data-[sunday=true]:data-[currentMonth=true]:bg-pink data-[sunday=true]:red" >
    {day}
</div>

注意点

data属性は文字列になるので、number型をそのまま判定すると反映されません。
判定箇所にてダブルクォーテーション(シングルクォーテーションでも可)で囲ってあげる必要があります。

// statusはnumber型
// bgは反映されない
<div
    data-status={status}
    className={`rounded data-[status=0]:bg-gray data-[status=1]:bg-red data-[status=2]:bg-green`} >
    {label}
</div>
// statusはnumber型
// classNameをテンプレートリテラルにして、ダブルクォーテーションを記述すると、bgが反映される
<div
    data-status={status}
    className={`rounded data-[status="0"]:bg-gray data-[status="1"]:bg-red data-[status="2"]:bg-green`} >
    {label}
</div>

さいごに

いかがでしたでしょうか。
すこしでも誰かの役に立てれば幸いです。
これからも見やすいコーディングを心がけていきたいと思います💪🏻

エックスポイントワン技術ブログ

Discussion