カート
サムネ・商品名・数量ステッパー(−/+)・削除×を持つ明細行と、小計・送料・合計のサマリーを備えた買い物カゴ。数量変更や削除で行の金額と合計がその場で再計算される。
プレビュー
クリック
操作クリック/タップで動きます。
仕様書
- 向く場面
- カートページ・カートドロワーの明細
- 数量変更で合計を即時に見せたい買い物かご
- 送料無料ラインを合計に反映する EC
- 避ける場面
- 明細が数十行を超える業務発注(表形式が向く)
- 数量が変えられない定額サブスクの確認画面
- 構成要素
- 見出しと点数
- 明細行
- 数量ステッパー
- 削除ボタン
- 小計・送料・合計
- レジに進むボタン
- 持っている状態
- 通常
- ホバー
- 押下中
- 無効
- 空
- キーボード
Tab で各行の −/+/削除、最後にレジへ。Enter/Space で実行。空になるとレジが disabled
- 支援技術
−/+・削除は商品名入りの aria-label、数量は aria-live=polite、合計は視覚外の aria-live=polite で読み上げ。空は文言で示しレジを無効化。focus-visible の輪郭あり。reduced-motion で削除の退場を省略
- 動き
削除した行が右へ 10px ずれながら 200ms でフェードし、完了後に再計算
原則ヤコブの法則
デザインの要点
- 数量を変えたら行の金額・点数・送料・合計を同時に再計算する。1 か所でも遅れると信用を失う
- 送料無料ラインは合計に反映して初めて意味を持つ。5,000 円を切ったら送料 500 円を即座に足す
- 削除は 200ms で右へ抜けさせてから DOM を消す。即消しだと何が消えたか分からない。reduced-motion は即時
- 削除ボタンは 14px の×でも 28px の当たり判定を取り、名前に商品名を入れる。「削除」だけでは何を消すか読めない
コード(コピーして使えます)
<div class="cs-panel">
<div class="cs-head">
<span class="cs-head-title">カート</span>
<span class="cs-head-count" id="csCount">3点</span>
</div>
<ul class="cs-items" id="csItems">
<li class="cs-item" data-price="2480" data-qty="1">
<span class="cs-thumb" style="background:linear-gradient(135deg,#dce5f7,#c3d2f0)" aria-hidden="true"></span>
<div class="cs-mid">
<p class="cs-name">オーガニックコットンTシャツ</p>
<div class="cs-stepper">
<button class="cs-step cs-minus" aria-label="数量を減らす">−</button>
<span class="cs-qty" aria-live="polite">1</span>
<button class="cs-step cs-plus" aria-label="数量を増やす">+</button>
</div>
</div>
<div class="cs-right">
<button class="cs-remove" aria-label="削除">
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" aria-hidden="true">
<line x1="3" y1="3" x2="11" y2="11" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
<line x1="11" y1="3" x2="3" y2="11" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
</svg>
</button>
<span class="cs-line-total">¥2,480</span>
</div>
</li>
<li class="cs-item" data-price="3980" data-qty="1">
<span class="cs-thumb" style="background:linear-gradient(135deg,#f0e2d0,#e2cba8)" aria-hidden="true"></span>
<div class="cs-mid">
<p class="cs-name">レザーミニ財布</p>
<div class="cs-stepper">
<button class="cs-step cs-minus" aria-label="数量を減らす">−</button>
<span class="cs-qty" aria-live="polite">1</span>
<button class="cs-step cs-plus" aria-label="数量を増やす">+</button>
</div>
</div>
<div class="cs-right">
<button class="cs-remove" aria-label="削除">
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" aria-hidden="true">
<line x1="3" y1="3" x2="11" y2="11" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
<line x1="11" y1="3" x2="3" y2="11" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
</svg>
</button>
<span class="cs-line-total">¥3,980</span>
</div>
</li>
<li class="cs-item" data-price="1280" data-qty="2">
<span class="cs-thumb" style="background:linear-gradient(135deg,#dcefe0,#bfe0c8)" aria-hidden="true"></span>
<div class="cs-mid">
<p class="cs-name">アロマキャンドル</p>
<div class="cs-stepper">
<button class="cs-step cs-minus" aria-label="数量を減らす">−</button>
<span class="cs-qty" aria-live="polite">2</span>
<button class="cs-step cs-plus" aria-label="数量を増やす">+</button>
</div>
</div>
<div class="cs-right">
<button class="cs-remove" aria-label="削除">
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" aria-hidden="true">
<line x1="3" y1="3" x2="11" y2="11" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
<line x1="11" y1="3" x2="3" y2="11" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
</svg>
</button>
<span class="cs-line-total">¥2,560</span>
</div>
</li>
</ul>
<p class="cs-empty" id="csEmpty" hidden>カートは空です</p>
<span class="cs-sr" id="csStatus" aria-live="polite"></span>
<div class="cs-summary">
<div class="cs-sum-row">
<span>小計</span>
<span class="cs-sum-val" id="csSubtotal">¥9,020</span>
</div>
<div class="cs-sum-row">
<span>送料</span>
<span class="cs-sum-val" id="csShipping">無料</span>
</div>
<div class="cs-sum-row cs-sum-total">
<span>合計</span>
<span class="cs-sum-val" id="csTotal">¥9,020</span>
</div>
</div>
<button class="cs-checkout" id="csCheckout">レジに進む</button>
</div>