本文へスキップ

商品カード

画像・お気に入り♥・SALEタグ・ブランド・商品名・星評価・価格(元値は取り消し線)・カート追加ボタンを収めたEC定番の商品カード。ホバーでふわっと持ち上がる。

ENGLISH

Product Card

  • JS
約213行領域別 / EC・商品 の一覧 →

プレビュー

クリック

操作クリック/タップで動きます。

仕様書

向く場面
  • 商品一覧・検索結果・レコメンド枠
  • 3〜4 列のグリッドで比較させる EC
  • 一覧から直接カートに入れられる単一バリエーション商品
避ける場面
  • 色・サイズ選択が必須の商品(詳細へ遷移させる)
  • 商品詳細の主役表示(1 枚を大きく見せる用途)
構成要素
  • 商品画像とSALEタグ
  • お気に入りボタン
  • ブランド・商品名
  • 星評価
  • 価格と元値
  • カートボタン
持っている状態
  • 通常
  • ホバー
  • 押下中
  • 成功
キーボード

Tab でお気に入り→カートへ、Enter/Space で切替・追加

支援技術

お気に入りは名前「お気に入り」を固定し aria-pressed だけ切替。星は role=img+aria-label で点数。元値は隠しテキスト「割引前」を併記。追加完了は視覚外の aria-live=polite で読み上げ。reduced-motion で浮き上がり停止

動き

ホバーでカードが 6px 浮き上がり影が濃くなる 220ms。ハート押下 0.88 倍 150ms バウンス。追加表示は 1.4s 後に戻る

デザインの要点

  • 画像は aspect-ratio 5/4 で高さを固定する。一覧で並べたときカードの高さが揃わないと視線が迷う
  • ホバーの浮き上がりは transform と box-shadow だけで作る。レイアウトを動かさないので一覧でもガクつかない
  • 星は背景の灰 5 個の上に色付き 5 個を width で切って重ねる。4.5 のような小数を 1 つの仕組みで出せる
  • 追加ボタンは 44px 確保し、押したら 1.4 秒だけ緑+「✓ 追加しました」に変える。連打はタイマーを積み直して吸収

使いどころ

EC一覧・検索結果・レコメンド枠のように、同型のカードを複数並べて商品を比較検討させる場面の定番。1枚に収める情報量(画像・タグ・お気に入り・ブランド・商品名・評価・価格・カートボタン)が多いため、幅260px程度を基準に3〜4列のグリッドで並べる使い方に最適化されており、1枚だけを大きく見せる商品詳細ページの主役表示には向かない。SALEタグやカート追加後の「✓ 追加しました」という即時フィードバックがあるため、購入までの導線を一覧画面で完結させたいカジュアルなECに向く一方、色・サイズなどのバリエーション選択が必須の商品では、この場でカートに追加すると選択漏れのまま注文が進む恐れがあるため、バリエーション選択が要る商品は詳細ページへの遷移ボタンに差し替えるべきだ。

仕組み

お気に入りボタン(pc-fav)はaria-label="お気に入り"を固定したままaria-pressedの真偽値だけをトグルし、CSSの[aria-pressed="true"]セレクタでハートの塗りと色を切り替えている(状態の正本をARIA属性に置き、見た目はそこから導く)。星評価は背景の塗りつぶし無し★5個(pc-stars-bg)の上に、色付きの★5個(pc-stars-fg)をwidth: 90%でoverflow: hiddenにして重ね、パーセンテージ分だけ着色部分を見せることで4.5のような小数点の評価を表現している。カート追加ボタンはクリックのたびにclassList.add("is-added")で背景色を緑に変え、textContentを「✓ 追加しました」に差し替えて1.4秒後に元に戻すが、この処理はsetTimeoutを毎回clearTimeoutしてから積み直すことで、連打してもタイマーが多重に走らないようにしている。カード全体のホバー演出(pc-card:hover)はtransform: translateY(-6px)とbox-shadowの強化だけで構成され、layoutプロパティを触らないためスクロールが多い一覧画面でもガクつきにくい。

実装の注意

星評価は<span role="img" aria-label="5点満点中4.5点">で全体をまとめて画像として扱っているため読み上げ上は問題ないが、実装がCSSのwidth: 90%による塗りつぶしなので、評価値が変わるたびにこのパーセンテージをJS側で計算してインラインstyleに反映する仕組みが呼び出し側に必要になる。テンプレートをそのまま複製すると星の割合が固定値のまま流用されるミスが起きやすい。カート追加時の「✓ 追加しました」というフィードバックはボタンのtextContentの書き換えだけでは自動的に読み上げられるとは限らないので、この見本は視覚外のaria-live領域にも同じ文言を書いている(複製するときにこの領域を落としやすい)。またpc-price-old(取り消し線価格)は視覚的にはtext-decoration: line-throughだけで、読み上げでは通常の価格と区別なく金額として読まれるため、隠しテキスト「割引前」を添えている。これを外すと初見のユーザーには元値なのか現在価格なのか誤解される。

アクセシビリティ

pc-fav(お気に入りボタン)はaria-label="お気に入り"を固定し、状態はaria-pressedだけで伝えている。ARIAのトグルボタンパターンの原則どおりで、よくある失敗はラベルを「お気に入りから削除」に変えつつpressed=trueにすることで、『「削除」ボタンが押された状態』という矛盾した読み上げになる。動作ラベルを使いたいならaria-pressedを外す、のどちらかに寄せる。星評価はrole="img"とaria-labelで数値をまとめて伝えているため追加対応は不要。カート追加時のフィードバックは、ボタン文言の差し替えに加えて視覚外のaria-live="polite"領域(pc-sr)へ「カートに追加しました」を書き込み、読み上げでも完了が分かるようにしてある。価格表示はpc-price-oldに視覚的に隠したテキスト「割引前」を添えて、取り消し線の意味を読み上げでも伝える(pc-priceとpc-price-oldをまとめてaria-label="6,980円、元の価格9,800円から割引"のように上書きする手もある)。カートボタンの最小高さは44pxを確保しており(min-height: 44px)、モバイルのタップ領域としては妥当なサイズになっている。

調整して使う

調整しやすいのは3点。SALEタグ(pc-tag)は固定文言だが、色と文言を変えれば「新着」「残りわずか」といった別のバッジ用途に転用できる。評価表示は★の代わりに数値バーやハートに差し替えても、同じoverflow: hiddenの塗り分けテクニックがそのまま使える。カートボタンの確認演出は、色変化+テキスト差し替えの代わりにチェックマークのアイコンだけをフェードインさせる軽量な演出にすると、テキストの長さがボタン幅を圧迫する問題を避けられる。画像部分(pc-media)は現在SVGのプレースホルダーだが、実運用では<img loading="lazy">に差し替えつつaspect-ratio: 5/4を保つことで、複数枚並んだグリッドの高さがガタつかない。

コード(コピーして使えます)

<div class="pc-card" id="pcCard">
  <div class="pc-media">
    <span class="pc-tag">SALE</span>
    <button class="pc-fav" id="pcFav" aria-pressed="false" aria-label="お気に入り">
      <svg class="pc-heart" width="20" height="20" viewBox="0 0 20 20" fill="none" aria-hidden="true">
        <path d="M10 17s-6.2-3.9-8-8.1C.9 6.1 2.4 3.5 5.2 3.5c1.8 0 3 1 4.8 3 1.8-2 3-3 4.8-3 2.8 0 4.3 2.6 3.2 5.4C16.2 13.1 10 17 10 17z" stroke="currentColor" stroke-width="1.6" stroke-linejoin="round"/>
      </svg>
    </button>
    <svg class="pc-img" viewBox="0 0 200 160" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
      <rect width="200" height="160" fill="url(#pcg)"/>
      <rect x="66" y="40" width="68" height="86" rx="8" fill="#fff" opacity=".55"/>
      <circle cx="100" cy="70" r="18" fill="#fff" opacity=".7"/>
      <rect x="78" y="98" width="44" height="6" rx="3" fill="#fff" opacity=".5"/>
      <defs>
        <linearGradient id="pcg" x1="0" y1="0" x2="200" y2="160" gradientUnits="userSpaceOnUse">
          <stop stop-color="#dce5f7"/>
          <stop offset="1" stop-color="#c3d2f0"/>
        </linearGradient>
      </defs>
    </svg>
  </div>
  <div class="pc-body">
    <p class="pc-brand">CHIITSURU</p>
    <p class="pc-title">リネンブレンド オーバーシャツ</p>
    <div class="pc-rate">
      <span class="pc-stars" role="img" aria-label="5点満点中4.5点">
        <span class="pc-stars-bg">★★★★★</span>
        <span class="pc-stars-fg" style="width:90%">★★★★★</span>
      </span>
      <span class="pc-rate-num">4.5</span>
      <span class="pc-reviews">(128)</span>
    </div>
    <div class="pc-price-row">
      <span class="pc-price">¥6,980</span>
      <span class="pc-price-old"><span class="pc-sr">割引前 </span>¥9,800</span>
    </div>
    <button class="pc-cart" id="pcCart">カートに入れる</button>
    <span class="pc-sr" id="pcStatus" aria-live="polite"></span>
  </div>
</div>

タグ

同じカテゴリ「EC・商品」のほかのパーツ

関連パーツ