並び替えメニュー
「並び替え」ボタンでメニューを開き、価格・評価・新着を選ぶと商品カードが FLIP で滑らかに入れ替わる。ボタンには現在の並びを常に表示する。
プレビュー
クリック
操作クリック/タップで動きます。
仕様書
- 向く場面
- 商品カードの並びを価格・評価・新着で切り替える一覧
- 現在の並び順をボタン文言に常に出したい画面
- 並び替えで要素の移動を目で追わせたいグリッド
- 避ける場面
- 表(テーブル)の列見出しで並べ替える画面
- 並び替え候補が7つを超える(listbox が長い)
- 構成要素
- 件数
- 並び替えボタン(現在値)
- メニュー
- 選択肢(チェック印)
- カードグリッド
- 持っている状態
- 通常
- ホバー
- フォーカス
- 押下中
- キーボード
ボタンで ↑↓/Enter/Space で開くとリストへフォーカスが移る。↑↓ で候補を移動、Home/End で端、Enter/Space で確定、Esc で閉じてボタンへ戻る
- 支援技術
ボタンに aria-haspopup=listbox・aria-expanded・aria-controls。メニューは role=listbox(tabindex=-1 でフォーカスを受け aria-activedescendant で位置を伝える)、候補は option+aria-selected
- 動き
FLIP でカードが元位置から 350ms cubic-bezier(0.2,0.7,0.2,1) で移動(並び替えを追える)、矢印の回転 200ms。reduced-motion で無効
デザインの要点
- ボタンの文言は「並び替え」ではなく「並び替え: 価格が安い順」。いまの状態が見えないメニューは開いて確かめる手間を生む
- 並び替えは要素が移動して見えると追える。FLIP なら DOM 順を変えた後に transform で元位置から動かすだけで済む
- 既定の「おすすめ順」を先頭に置き、選択中はチェック印。同じものを選び直しても何も起きないのが正しい
コード(コピーして使えます)
<div class="smr">
<div class="smr-bar">
<p class="smr-total">6 件</p>
<div class="smr-menu-wrap">
<button id="smr-btn" class="smr-btn" type="button" aria-haspopup="listbox" aria-expanded="false" aria-controls="smr-menu">
<span class="smr-btn-label">並び替え: <strong id="smr-current">おすすめ順</strong></span>
<svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.8" aria-hidden="true"><path d="m4 6 4 4 4-4"/></svg>
</button>
<ul id="smr-menu" class="smr-menu" role="listbox" aria-label="並び順" tabindex="-1" hidden></ul>
</div>
</div>
<ul id="smr-grid" class="smr-grid" aria-label="商品"></ul>
</div>