ハコヅミを作る #23:カード表示を正方形にそろえ、キャンプを年ごとに区切る

前回(#22)に続いて、見た目の手直しです。今回は、#20で作ったカード表示を直します(#110・#112)。

前回は「サンプル画像を見て決めれば、あとからの直しが出ない」という話でした。今回は、サンプルを見て決めても、使ってみたら直したくなった話です。


「正方形にしたい」の、2通りの読み方

メモは、こうでした。

ギアとキャンプのカード表示のカード部分は正方形にしたい

今のカードは、画像の下に文字が続く形です。文字の行数がカードごとに違うので、高さがばらばらです。

「カード部分は正方形」には、2通りの読み方があります。

  • 案A:カード全体(画像+文字)を正方形にする
  • 案B:画像を正方形にして、文字は下に続ける(今に近い)

どちらか決めきれなかったので、両方のサンプルが出てきました。

ギアのカードのサンプル。左は今で、カードの高さがばらばら。中央の案Aは、カード全体が正方形で、同じ大きさにそろっている。画像は上の細い帯になる。右の案Bは、画像が正方形で、文字が下に続く縦長のカード

ギアのカード(左から、今/案A:カード全体を正方形/案B:画像を正方形)

キャンプのカードのサンプル。左は今。中央の案Aは、カード全体が正方形で、画像は細い帯、その下に名前・2段の日付・プランのバッジ・進み具合が詰まっている。右の案Bは、画像が正方形で、文字が下に続く

キャンプのカード(左から、今/案A/案B)

画像は、今の画面に見た目だけを仮に当てて撮ったサンプルです。ギアは#7で取り込んだ実際のもので、キャンプ場は記事用の架空のものです。画像付きのカードには、色だけの絵を付けています。

案A は、タイルがきれいにそろいます。その代わり、文字を入れた残りが画像になるので、スマホの幅では、画像が細い帯になります。キャンプは文字が多いので、特に細い。Claude Code のおすすめは「キャンプは案B」でした。

それでも、ギアもキャンプも 案A にしました。画像を大きく見ることより、一覧としてそろって見えるほうを取っています。おすすめと違うほうを選べるのも、両方の画像が並んでいるからです。

中身の並び

あわせて、カードの中身を整えました。

  • ギア:画像・名称・メーカー・コンテナ・評価の順で、1つずつ行を分ける(メーカーとコンテナのバッジを、横に並べない)
  • キャンプ:日付を、#22のリストと同じ書き方(曜日・泊数付き)にする。プランはバッジ、全部積んだら「積み込み済み」
  • 名前は1行に収め、長いときは「…」で切る

キャンプの日付は、カードの幅では1行に入りません。「必ず2段になってしまうので、2段目だけ右寄せにして」と頼んで、開始日を左、終了日と泊数を右に寄せた2段にしました。

正方形の作り方

Tailwind では、カードに aspect-square(縦横を同じにする)と、縦に並べる flex-col を付けます。文字の部分は中身の高さのまま(flex-none)、画像は残りの高さいっぱい(flex-1)です。

<a class="flex aspect-square flex-col overflow-hidden rounded-box border border-line">
	<img src={gear.imageUrl} alt="" loading="lazy" class="min-h-0 w-full flex-1 object-cover" />
	<div class="flex-none space-y-0.5 p-2">
		<p class="truncate text-sm font-semibold">{gear.productName}</p>
		...
	</div>
</a>

画像には min-h-0 を付けています。flex の中の要素は、そのままでは中身より小さくならないので、付けておかないと、画像が縮まずにカードが正方形からはみ出すことがあります。


使ってみたら、直したくなった

開発環境で実際に見てみると、3つ直したくなりました。

  1. キャンプの日付は、やはり1行に収めたい(曜日を外してでも)
  2. カードとカードの間を、もう少し詰めたい
  3. キャンプを、年ごとに区切りたい

1 は、自分で「2段にして右寄せ」と頼んだものです。サンプルでも見ていました。それでも、実際の画面で何枚も並ぶと、2段の日付が場所を取って、落ち着きません。サンプルは「選ぶ」ためには十分でも、「使った感じ」までは分からない、ということです。

ここでも、先にサンプルを頼みました。

年の区切り:見出しか、切り替えか

「年ごとにタブで区切る」も、2通りに読めます。

年の区切りのサンプル。左は今で、年の区切りがない。中央の案Aは、「2026年」「2025年」の見出しでカードをまとめ、見出しの右に件数。日付は年なしの1行。右の案Bは、「2026年(4)」「2025年(2)」のタブで年を切り替える形で、選んだ年だけが出る。日付は年付きで、末尾が「…」で切れている

年の区切り(左から、今/案A:年ごとに見出しで区切る/案B:年を切り替えるタブ)

  • 案A:年ごとの見出しで区切り、全部の年を1つの画面に続けて出す
  • 案B:年を切り替えるタブにして、選んだ年だけを出す

キャンプは年に数回です。当面は1画面で見渡せるほうが使いやすいので、案A にしました。見出しは、ギアのカテゴリと同じタブの形(#22)なので、新しい見た目は増えていません。

このサンプルで、もう1つ分かったことがあります。右の案B は、日付に年を付けたままです。年を付けると、スマホの幅では1行に入りきらず、「…」で切れています。年ごとに区切るなら、年は見出しで分かるので、カードの日付からは外せます。

「曜日を入れても、1行に収まる?」

年を外すなら、その分、曜日を戻せるかもしれません。聞いてみました。

日付は確かに年を外してOK(その場合、曜日を入れても1行に収まる?収まるのであれば曜日は出したい)

返ってきたのは、「たぶん収まります」ではなく、実際に当てて測った結果でした。

画面の幅 曜日あり・文字 12px(今の大きさ) 曜日あり・文字 11px 曜日なし
375px 月も日も2桁の日付だけ、5px はみ出して「…」になる 全部収まる 全部収まる
390px 全部収まる(余裕は 2px) 全部収まる 全部収まる
広い幅(3列) 全部収まる 全部収まる 全部収まる
幅 375px での、日付の3つの案。左は曜日あり・文字 12px で、上の2枚のカードの日付の末尾が「…」で切れている。中央は曜日あり・文字 11px で、すべて1行に収まっている。右は曜日なしで、すべて収まっている

幅 375px での見比べ(左から、曜日あり 12px/曜日あり 11px/曜日なし)。左の上の2枚だけ、末尾が切れている

はみ出すのは、「11/21(土)〜11/23(月)・2泊」のように、月も日も2桁の日付だけです。日付の行だけ文字を 1px 小さくすれば、全部収まります。曜日あり・11px に決めました。

測り方は単純で、日付の要素の「中身の幅」と「見えている幅」を比べるだけです。

// はみ出して「…」になっているか
el.scrollWidth > el.clientWidth

同じ確かめ方を、そのまま E2E にも入れました。幅 375px で、月も日も2桁の日付がはみ出さないことを確かめています。

ただし、#21で書いたとおり、E2E は Web フォントを読み込みません。フォントが違えば、文字の幅も違います。実際のフォントでは、手元でフォントを読み込んだ画面を撮って、同じ数字を測って確かめました。自動テストで確かめたことと、目と手で確かめたことは、PR に分けて書いています。


受入のあとの直しは、新しい Issue にする

進め方で迷ったのは、この直しをどの Issue でやるかです。

カードを正方形にした Issue(#110)は、PR がマージされて、受入確認を待っている状態でした。そこに直しを足すこともできます。ただ、年ごとの区切りは、リスト表示にも入る、#110 より大きい変更です。

  • #110 は、今の状態で受入 OK にする
  • 直しは、新しい Issue(#112)にする

と分けました。#110 の AC は「2段目が右寄せになっている」のままで、受入のコメントに「受入のあとで出た直しは、別の Issue で行う」と残しています。Issue の AC を書き換えて、なかったことにはしません。一度そう決めて作った、という経緯が残るほうが、あとで見返したときに分かりやすいためです。


できあがり

実装後のスマホの幅の画面。左はキャンプのカード表示で、「2026年」「2025年」の見出しの下に、正方形のカードが2列で並び、日付は曜日付きの1行。中央はキャンプのリスト表示で、同じ年の見出しで区切られている。右はギアのカード表示で、正方形のカードが、狭い間で並ぶ

スマホの幅(左から、キャンプのカード表示/リスト表示/ギアのカード表示)

実装後の広い幅の画面。左はキャンプのカード表示(3列)、右はリスト表示。どちらも年の見出しで区切られ、見出しの右に件数が出ている

広い幅(左:カード表示、右:リスト表示)

  • カードの間は、12px から 6px に
  • 年の見出しの右に、その年の件数
  • 年ごとの区切りは、リスト表示にも入れた(表示を切り替えても、同じ並びになる)

年ごとにまとめる処理は、ほかのロジックと同じく src/lib/camps.ts に切り出して、ユニットテストしています。年をまたぐキャンプ(12/31〜1/1)は、開始日の年に入れました。


おわりに

  • 「正方形にしたい」のような一言にも、読み方が2つある。決めきれないときは、両方を並べてもらう
  • カード全体を正方形にするなら、文字は中身の高さ、画像は残りの高さにする(画像には min-h-0)
  • 「収まるか」は、聞くより測る。scrollWidth と clientWidth を比べれば、はみ出しが分かる
  • サンプルで選んでも、使ってみて変えたくなることはある。そのときは、受入済みの Issue を書き換えずに、新しい Issue にする

フォント(#21)から今回までの見た目の手直しは、6つの Issue をまとめて本番にリリースしました。

手元の E2E の時間についても、後日談があります。#20で「10分を超えるようになった」と書きましたが、原因の1つは、手元の D1 にたまったテストのデータ(ギアが7,000件あまり)でした。消して作り直したら、全件で7分ほどに戻っています。

次は、キャンプの日付の出し方の見直しと、おすすめ度・感想の追加を予定しています。

← トップページに戻る