本文へスキップ

ドラッグ並べ替え

ハンドルをつまんで縦リストの順序を入れ替える。掴んだ項目に合わせて他の項目がスッと動いて場所を空ける(並べ替えの定番)。PC・スマホ両対応。

プレビュー

ドラッグ

操作ドラッグ/スワイプで操作できます(PC・スマホ対応)。

仕様書

向く場面
  • ToDo・プレイリストなど順序が意味を持つ縦リスト
  • 5〜20件程度を指で並べ替えたい
  • 行の高さが均一な一覧
避ける場面
  • 行の高さが不揃いな一覧(スロット計算が崩れる)
  • 順序に意味がない一覧
  • キーボード代替なしで並べ替えを必須にする
構成要素
  • リスト
  • 項目
  • ドラッグハンドル
  • 順位番号
持っている状態
  • 通常
  • 押下中
キーボード

Tab で各行のハンドル button へ・↑↓ で1つ上/下へ移動(ハンドルにフォーカスが残る)。ドラッグはマウス・タッチ

支援技術

ハンドルは「ドラッグまたは↑↓キーで移動」の aria-label 付き button、順位は番号で示す。順序変更は sr-only の role=status で「N番目へ移動」を告知

動き

掴んだ項目は transition なしで追従、他の項目は translateY 0.18s で隙間を空ける。影 0.18s で持ち上がりを示す。reduced-motion では即時

デザインの要点

  • 掴んでいる間は DOM を動かさず transform だけで見せ、離した瞬間に一度だけ並べ替える。ドラッグ中に DOM を組み替えるとフォーカスと座標が飛ぶ
  • 間の項目は行の高さ+gap ぶん translateY でずらして隙間を空ける。ずらさないと「どこに落ちるか」が離すまで分からない
  • 掴めるのはハンドルだけにし、行本体は普通にタップできる状態を残す。行全体をドラッグ可能にすると縦スクロールと取り合う
  • ハンドルは button にして ↑↓ でも動かす。ドラッグしか無い並べ替えは、キーボードと読み上げでは順序を変えられない
実装メモ

ハンドルの Pointer Events でドラッグを検知し、掴んだ項目は指に追従(transform で移動・transition なし)、間の項目は行の高さ分だけ translateY でずらして「隙間を空ける」ことで並べ替えを表現します。他項目には transition を効かせるのでスッと動きます。離すと実際のDOM順を組み替えて番号を振り直します。ハンドルに touch-action:none を付け、縦ドラッグがスクロールと衝突しないようにしています(均等な行高さが前提)。ハンドルは button なので Tab で届き、↑↓ キーでも1つずつ入れ替えられます。

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

<ul class="dr-list" id="dr-list">
  <li class="dr-item"><button class="dr-handle" aria-label="ドラッグまたは↑↓キーで移動">⠿</button><span class="dr-rank"></span>牛乳を買う</li>
  <li class="dr-item"><button class="dr-handle" aria-label="ドラッグまたは↑↓キーで移動">⠿</button><span class="dr-rank"></span>資料をまとめる</li>
  <li class="dr-item"><button class="dr-handle" aria-label="ドラッグまたは↑↓キーで移動">⠿</button><span class="dr-rank"></span>ジムに行く</li>
  <li class="dr-item"><button class="dr-handle" aria-label="ドラッグまたは↑↓キーで移動">⠿</button><span class="dr-rank"></span>本を返却する</li>
  <li class="dr-item"><button class="dr-handle" aria-label="ドラッグまたは↑↓キーで移動">⠿</button><span class="dr-rank"></span>友人に返信</li>
</ul>
<p class="dr-status" role="status" aria-live="polite"></p>

タグ

同じカテゴリ「ナビ・リスト操作」のほかのパーツ

関連パーツ