logo

CSSのsubgridがめちゃくちゃ便利(Tailwind編)

2024-06-21
6 months ago

開発環境

  • next 14.1.0
  • tailwindcss 3.3.0

前提

CSSはtailwindを利用します。

本題

皆さんはフォーム画面を実装する時、ラベルとインプット要素を横並びにするようなレイアウトを作る時どうしてますか?

すぐに思いつくのはFlexBoxを利用する方法だと思います。

例えばこんな感じのフォームです。

コードサンプル

export const DemoForm = () => {
  return (
    <form className="flex flex-col gap-2 w-full" action="">
      <div className="flex gap-2">
        <label htmlFor="name">名前</label>
        <input className="border" id="name" name="name" type="text" />
      </div>
      <div className="flex gap-2">
        <label htmlFor="email">メールアドレス</label>
        <input className="border" id="email" name="email" type="email" />
      </div>
      <div className="flex gap-2">
        <label htmlFor="company">会社名</label>
        <input className="border" id="company" name="company" type="text" />
      </div>
    </form>
  );
};

縦並びと横並びを利用して実装しています。

ただ、見て分かる通り、インプット要素が揃っていないのでガタガタになってしまっています。

ラベルの横幅が固定であればwidthを設定することで整えることはできますが、ラベルの文字が利用シーンで異なる、汎用的な利用を考えると、この対応では不十分です。


そういう時に、Gridを利用します。

export const DemoForm = () => {
  return (
    <form className="grid gap-2 w-full grid-cols-[max-content_1fr]" action="">
      <div className="grid grid-cols-subgrid col-span-2">
        <label htmlFor="name">名前</label>
        <input className="border" id="name" name="name" type="text" />
      </div>
      <div className="grid grid-cols-subgrid col-span-2">
        <label htmlFor="email">メールアドレス</label>
        <input className="border" id="email" name="email" type="email" />
      </div>
      <div className="grid grid-cols-subgrid col-span-2">
        <label htmlFor="company">会社名</label>
        <input className="border" id="company" name="company" type="text" />
      </div>
    </form>
  );
};

ポイントはGridの入れ子構造で、subgridを利用していることです。

子要素(grid)の列を親要素(grid)の列に合わせることで、整列させることができます。

今回のケースだと、「メールアドレス」の領域が一番大きくなり、「名前」「会社名」がその大きさと揃います。

また、親要素(grid)のgapは子要素(grid)にも引き継がれるので、子要素でgapを定義する必要はなくなりました。

さいごに

今回はフォーム画面で紹介しましたが、他にもブログなどでよくあるカードにもsubgridを活用できそうです。

参照