Sortable.jsで実装可能なリストのシンプルな並び替え方法8選

Sortable.jsを使ったドラッグ&ドロップによるリスト並び替えJS
この記事は約26分で読めます。

※本記事のコンテンツは、利用目的を問わずご活用いただけます。実務経験10000時間以上のエンジニアが監修しており、基礎知識があれば初心者にも理解していただけるように、常に解説内容のわかりやすさや記事の品質に注力しております。不具合・分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。(理解できない部分などの個別相談も無償で承っております)
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

●Sortable.jsとは

Sortable.jsは、リストやグリッドなどの要素をドラッグ&ドロップで並び替えることができる、軽量でシンプルなJavaScriptライブラリです。

jQueryのようなフレームワークに依存せず、純粋なJavaScriptで書かれているため、どんなプロジェクトにも簡単に組み込むことができます。

○特徴

Sortable.jsの大きな特徴は、直感的でスムーズなドラッグ&ドロップ操作を実現している点です。

マウスカーソルに合わせてリストの項目が動き、ドロップした位置に自然に収まるアニメーションが備わっています。

また、ドラッグ可能な要素の範囲を柔軟に設定できたり、ドラッグ中の要素のスタイルを変更できたりと、カスタマイズ性も高いのが魅力です。

さらに、Sortable.jsは複数のリストを連携させることもできます。

例えば、「TODO」「進行中」「完了」のようなステータス管理のリストを作成し、タスクをドラッグ&ドロップで別のリストに移動させるといったことも、Sortable.jsなら簡単に実装できるのです。

○導入方法

Sortable.jsを使うには、公式サイトからライブラリをダウンロードするか、CDNを利用するのが一般的です。

ダウンロードした場合は、HTMLファイルでscriptタグを使ってSortable.jsを読み込みます。

<script src="sortable.min.js"></script>

CDNを利用する場合は、このようにscriptタグのsrc属性にCDNのURLを指定します。

<script src="https://cdn.jsdelivr.net/npm/sortablejs@latest/Sortable.min.js"></script>

○基本的な使い方

Sortable.jsを使ったリストの並び替え機能を実装するには、次のようなステップを踏みます。

  1. 並び替え可能にしたいリストを用意する
  2. JavaScriptでSortableクラスのインスタンスを作成する
  3. オプションを指定してカスタマイズする

まず、HTMLでul要素やol要素を使ってリストを作成します。

次に、JavaScript内でSortable.create()メソッドを呼び出し、第一引数にリストの要素、第二引数にオプションを指定します。

これだけで、リストがドラッグ&ドロップで並び替えできるようになります。

○サンプルコード1:シンプルなリスト並び替え

ここでは、シンプルなリストの並び替えを実装したサンプルコードを紹介します。

<ul id="my-list">
  <li>りんご</li>
  <li>ばなな</li>
  <li>みかん</li>
</ul>
const el = document.getElementById('my-list');
const sortable = Sortable.create(el);

これだけのコードで、id属性が「my-list」のul要素の中の項目がドラッグ&ドロップで並び替えできるようになります。

実行すると、リストの項目を自由に並び替えることができます。

りんご
みかん
ばなな

このように、Sortable.jsを使えば、わずか数行のコードでリストの並び替え機能を実現できます。

しかも、アニメーションが自動的に付与されるため、見た目にも美しく仕上がります。

●Sortable.jsのオプション

前回は、Sortable.jsの基本的な使い方を見てきました。

シンプルなリストの並び替えなら、ほんの数行のコードで実現できることがわかったと思います。

でも、実際のWebサイトやアプリケーションでは、もっと細かいカスタマイズが必要になるケースが多いですよね。

そこで、今回はSortable.jsのオプションを使って、ドラッグ&ドロップ操作をより柔軟にコントロールする方法を見ていきましょう。

例えば、ドラッグできる範囲を限定したり、ドラッグ中の要素のスタイルを変更したり、並び替え後に特定の処理を実行したりといったことが可能になります。

これらのテクニックを身につければ、よりインタラクティブで使いやすいUIを実装できるようになるはずです。プログラミングが苦手だという方も、コードを見ながら一緒に試してみてください。

きっと、Sortable.jsの利便性の高さを実感していただけると思います。

それでは、具体的なオプションの使い方を見ていきましょう。

○サンプルコード2:ドラッグハンドルの指定

リストの項目全体をドラッグ可能にするのではなく、特定の要素だけをハンドルにしてドラッグしたいことがあります。

そんな時は、handleオプションを使って、ドラッグハンドルとなる要素のセレクターを指定しましょう。

<ul id="my-list">
  <li><span class="handle">::</span>りんご</li>
  <li><span class="handle">::</span>ばなな</li>
  <li><span class="handle">::</span>みかん</li>
</ul>
const el = document.getElementById('my-list');
const sortable = Sortable.create(el, {
  handle: '.handle', // ドラッグハンドルのセレクターを指定
});
.handle {
  cursor: move;
  display: inline-block;
  margin-right: 10px;
}

実行すると、「::」マークの部分だけをドラッグハンドルにできました。

::りんご
::ばなな
::みかん

このコードでは、各li要素の中に「::」という文字列を囲むspan要素を追加し、それにhandle
というクラス名を付けています。

そして、JavaScriptでSortableを初期化する際に、handleオプションでそのクラス名を指定しているわけです。

CSSでは、ドラッグハンドルとなるspan要素にcursorプロパティでmoveの値を設定し、ユーザーにドラッグ可能であることを視覚的に伝えています。

こうすることで、span要素の部分だけがドラッグハンドルになり、そこをマウスで掴んでドラッグすれば並び替えができるようになります。

リスト全体をドラッグ可能にするのは避けたいけど、直感的な操作は維持したい。

そんな時にこのテクニックが役立つでしょう。ほんの少しのコードで、UI/UXを大きく改善できる好例だと言えます。

○サンプルコード3:ドラッグ中の要素のスタイル変更

並び替え操作中は、ドラッグしている要素を目立たせたいことがありますよね。

そんな時は、ghostClassオプションを使って、ドラッグ中の要素に
クラス名を付与しましょう。

そのクラス名に対してCSSを適用すれば、お好みのスタイルに変更できます。

<ul id="my-list">
  <li>りんご</li>
  <li>ばなな</li>
  <li>みかん</li>
</ul>
const el = document.getElementById('my-list');
const sortable = Sortable.create(el, {
  ghostClass: 'ghost', // ドラッグ中の要素のクラス名を指定
});
.ghost {
  opacity: 0.5;
  background-color: #F8F8F8;
}

実行すると、ドラッグ中の要素が半透明になり、背景色が変わります。

りんご
ばなな
みかん ← ドラッグ中

JavaScriptでghostClassオプションに’ghost’を指定し、ドラッグ中の要素にghostというクラス名が付与されるようにしています。

CSSでは、ghostクラスに対して、opacityで透明度を50%に設定し、background-colorで背景色を薄いグレーに変更しています。

これにより、ドラッグ中の要素が視覚的に目立つようになります。

ユーザーに並び替え操作中であることをしっかりとフィードバックできれば、スムーズで直感的な操作性が実現できるはずです。

Webサイトやアプリケーションの印象を大きく左右する部分ですから、ぜひ積極的にカスタマイズしてみてください。

○サンプルコード4:並び替え後のイベント処理

並び替えが完了した後に、何らかの処理を実行したくなることがあります。

例えば、並び替え後のデータをサーバーに送信したり、関連する別の要素を更新したりといったことです。

そんな時は、onEndイベントを利用しましょう。

<ul id="my-list">
  <li>りんご</li>
  <li>ばなな</li>
  <li>みかん</li>
</ul>
<p id="result"></p>
const el = document.getElementById('my-list');
const sortable = Sortable.create(el, {
  onEnd: function (evt) {
    // 並び替え後の順序を出力
    const result = document.getElementById('result');
    result.textContent = ' 並び替え後の順序: ' + this.toArray();
  },
});

実行すると、並び替え後のリストの順序が、p要素に出力されます。

りんご
みかん
ばなな

並び替え後の順序: 0,2,1

onEndオプションに、並び替え完了時に実行したい処理を関数で指定します。

ここでは、SortableインスタンスのメソッドtoArray()を使って、並び替え後のリストの順序を配列で取得し、それを画面に出力しています。

このように、Sortable.jsではイベントハンドラを使ってさまざまな処理を実行できます。

例えば、データベースに並び替えの結果を保存したり、ドラッグ&ドロップを使った
アプリケーションのロジックを実装したりと、応用の幅は非常に広いです。

他にも、onStartイベントや、onMoveイベント、onAddイベント、onUpdateイベントなど、状況に応じて使い分けられるイベントが用意されています。

これを効果的に使いこなせば、ドラッグ&ドロップ機能の自由度がぐっと高まるでしょう。

○サンプルコード5:複数リストの連携

Sortable.jsでは、複数のリスト間で要素をドラッグ&ドロップで移動できます。

つまり、異なるリストの要素を自由に行き来できるようになるわけです。

その機能を実現するのが、groupオプションです。

<h2>買い物リスト</h2>
<ul id="list1" class="list-group">
  <li>トマト</li>
  <li>レタス</li>
  <li>ニンジン</li>
</ul>

<h2>お気に入り</h2>
<ul id="list2" class="list-group">
  <li>バナナ</li>
  <li>イチゴ</li>
</ul>
const lists = document.getElementsByClassName('list-group');

for (const list of lists) {
  Sortable.create(list, {
    group: 'shared', // 両方のリストで同じグループ名を指定
  });
}

実行すると、2つのリスト間で要素をドラッグ&ドロップで移動できます。

買い物リスト
トマト
レタス
ニンジン

お気に入り
バナナ
イチゴ
レタス ← list1から移動

JavaScriptでは、class属性にlist-groupを指定した要素を取得し、それぞれのリストに対してSortableを適用しています。

その際、groupオプションに’shared’という名前を指定することで、2つのリストが同一のグループに属するようにしています。

●よくあるエラーと対処法

Sortable.jsを使ってリストの並び替え機能を実装する際、うまく動かないことがあるかもしれません。

特に、JavaScriptを学び始めたばかりの方や、ライブラリの使用経験が浅い方は、エラーに遭遇して戸惑ってしまうことがあるでしょう。

ただ、よくあるエラーのほとんどは、ちょっとしたコードの修正や設定の見直しで解決できます。

ここでは、Sortable.jsを使う際に遭遇しやすいエラーをいくつか取り上げ、その原因と対処法を見ていきましょう。

これらのポイントを押さえておけば、スムーズにリストの並び替え機能を実装できるはずです。

エラーにぶつかっても、あわてずに冷静に対処することが大切ですね。

それでは、具体的なエラーの事例を見ていきましょう。

○ドラッグできない場合の確認ポイント

リストの項目をドラッグしようとしても、反応しないことがあります。

そんな時は、次の点を確認してみてください。

・HTMLの要素が正しく記述されているか
・JavaScriptでSortableのインスタンスが正しく作成されているか
・CSSでリストの項目が非表示になっていないか

特に、JavaScriptでSortableを初期化する際に指定するセレクターが間違っていると、ドラッグできなくなります。

HTMLのid属性やclass属性と、JavaScript側のセレクターが一致しているか、しっかりと確認しましょう。

また、CSSでdisplay: none;を指定してリストの項目を非表示にしていると、ドラッグできなくなります。

項目を非表示にする場合は、visibility: hidden;を使うようにしてください。

ここでは、ドラッグできない場合の原因と対処法の一例を見てみましょう。

<!-- HTMLのid属性がJavaScript側と一致していない -->
<ul id="my-list">
  <li>りんご</li>
  <li>ばなな</li>
  <li>みかん</li>
</ul>
// idの指定が間違っている
const el = document.getElementById('mylist');
const sortable = Sortable.create(el);
/* display: none;を指定するとドラッグできない */
#my-list li {
  display: none;
}

修正後のコード

<ul id="my-list">
  <li>りんご</li>
  <li>ばなな</li>
  <li>みかん</li>
</ul>
const el = document.getElementById('my-list');
const sortable = Sortable.create(el);
#my-list li {
  visibility: hidden;
}

実行すると、ドラッグ&ドロップでリストの並び替えができるようになります。

このように、エラーの原因を特定し、適切に修正することが重要です。

コードをよく読み、HTMLとJavaScript、CSSの連携を意識しながらデバッグしていきましょう。

○並び替え後の順序が保持されない問題

リストを並び替えた後、ページを再読み込みすると並び替え前の順序に戻ってしまうことがあります。

これは、並び替え後の順序がサーバー側に保存されていないために起こる問題です。

この問題を解決するには、次のような方法があります。

  1. 並び替え後の順序をサーバーに送信し、データベースに保存する
  2. LocalStorageを使って、クライアント側に並び替え後の順序を保存する
  3. URLのクエリパラメーターに並び替え後の順序を含め、ページの状態を保持する

1つ目の方法は、並び替え完了時にAjaxを使ってサーバーにデータを送信するなどの処理が必要になります。

2つ目の方法は、LocalStorageを使うことで、サーバーとのやり取りなしで並び替え後の順序を保持できます。

3つ目の方法は、URLにデータを含めることで、ページの再読み込み時に並び替え後の状態を再現できます。

ここでは、LocalStorageを使って並び替え後の順序を保持する例を紹介します。

const el = document.getElementById('my-list');
const sortable = Sortable.create(el, {
  onEnd: function (evt) {
    // 並び替え後の順序をLocalStorageに保存
    localStorage.setItem('order', this.toArray());
  },
});

// LocalStorageから並び替え後の順序を取得
const order = localStorage.getItem('order');
if (order) {
  sortable.sort(order.split(','));
}

実行すると、並び替え後の順序がLocalStorageに保存され、ページの再読み込み時にその順序が再現されます。

このコードでは、並び替え完了時にonEndイベントを使って、LocalStorageに並び替え後の順序を保存しています。

そして、ページの読み込み時にLocalStorageから順序を取得し、Sortableのsortメソッドを使ってリストの順序を復元しています。

並び替え後の状態を保持する方法は、アプリケーションの要件に応じて適切なものを選択してください。

ユーザーの利便性を損なわないよう、しっかりと設計することが大切ですね。

○IEでドラッグ動作がおかしい場合

Internet Explorer(IE)では、他のブラウザと比べてドラッグ&ドロップの動作が異なることがあります。

具体的には、ドラッグ中の要素の表示位置がマウスカーソルと同期しなかったり、ドロップ時のアニメーションが表示されなかったりといった問題が発生することがあります。

これは、IEがドラッグ&ドロップのAPIを独自に実装しているために起こる問題です。

IEでSortable.jsを使う場合は、次の点に注意してください。

・IEではドラッグ中の要素の位置が正しく表示されない場合がある
・IEではドロップ時のアニメーションが表示されない場合がある
・IEではSortableのオプションの一部が正しく機能しない場合がある

これらの問題に対処するには、IEを考慮したCSSの記述や、Sortableのオプションの調整が必要になることがあります。

ここでは、IEでドラッグ中の要素の位置を調整するCSSの例を紹介します。

.sortable-drag {
  /* IEでドラッグ中の要素の位置を調整 */
  -ms-transform: translateY(-50%);
  transform: translateY(-50%);
}

実行すると、IEでもドラッグ中の要素の位置がマウスカーソルと同期するようになります。

このように、IEの動作の違いを意識し、適切に対処することが重要です。

IEのバージョンによって動作が異なることもありますから、テストを十分に行い、問題がないことを確認しましょう。

Sortable.jsは、モダンブラウザに対応したライブラリですが、IEでも基本的な機能は問題なく使えます。

ただし、細かい動作の違いがあることを理解し、必要に応じて対処する必要があるのです。

●Sortable.jsの応用例

ここまで、Sortable.jsの基本的な使い方やオプションについて見てきましたが、実際の開発現場では、もっと複雑なUIを実装したいこともあるでしょう。

例えば、テーブルの行を並び替えたり、カードを自由に移動させたりといったことです。

そんな時でも、Sortable.jsの柔軟さを活かせば、さまざまな応用が可能です。

ここでは、少し発展的な使い方をいくつか紹介していきたいと思います。

すでにSortable.jsの基本を理解している方は、ぜひ応用力を高めるためにチャレンジしてみてください。

また、最近ではVue.jsやReactなどのモダンなJavaScriptフレームワークが人気ですが、Sortable.jsはそれらとの組み合わせも可能です。

フレームワークの中でドラッグ&ドロップ機能を実装する方法も見ていきましょう。

実務レベルの実装例を通して、Sortable.jsの可能性を感じていただければと思います。それでは、具体的なコードを見ていきましょう。

○サンプルコード6:テーブルの行の並び替え

表形式のデータを扱う際、行を並び替えたいことがあります。

Sortable.jsを使えば、テーブルの行をドラッグ&ドロップで並び替えることができます。

<table id="my-table">
  <thead>
    <tr>
      <th>品目</th>
      <th>価格</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>りんご</td>
      <td>100円</td>
    </tr>
    <tr>
      <td>ばなな</td>
      <td>80円</td>
    </tr>
    <tr>
      <td>みかん</td>
      <td>120円</td>
    </tr>
  </tbody>
</table>
const table = document.getElementById('my-table');
const tbody = table.querySelector('tbody');
const sortable = Sortable.create(tbody, {
  handle: 'td',
});

実行すると、テーブルの行をドラッグ&ドロップで並び替えることができます。

このコードでは、テーブルのtbody要素をSortableで初期化しています。

オプションのhandleには’td’を指定し、テーブルのセル(td要素)をドラッグハンドルにしています。

こうすることで、ユーザーはテーブルのセルをクリックしてドラッグすることで、行を自由に並び替えられるようになります。

表形式のデータの並び替えが直感的に行えるため、ユーザビリティの向上が期待できます。

ただし、テーブルのヘッダー行(thead内のtr要素)は並び替えの対象から外したい場合が多いでしょう。

そのため、tbody要素だけをSortableで初期化するようにしています。

このように、Sortable.jsを使えば、テーブルの行の並び替えも簡単に実装できます。

データの表示順を柔軟に変更できるUIを、ぜひアプリケーションに取り入れてみてください。

○サンプルコード7:カードの並び替えUIの作成

タスク管理アプリなどでは、カード形式のUIを使って情報を視覚的に整理することがあります。

Sortable.jsを使えば、カードをドラッグ&ドロップで自由に並び替えられるUIを実装できます。

<div id="card-container">
  <div class="card">
    <div class="card-header">タスク1</div>
    <div class="card-body">
      <p>タスクの説明1</p>
    </div>
  </div>
  <div class="card">
    <div class="card-header">タスク2</div>
    <div class="card-body">
      <p>タスクの説明2</p>
    </div>
  </div>
  <div class="card">
    <div class="card-header">タスク3</div>
    <div class="card-body">
      <p>タスクの説明3</p>
    </div>
  </div>
</div>
const container = document.getElementById('card-container');
const sortable = Sortable.create(container, {
  handle: '.card-header',
  animation: 150,
});
.card {
  width: 200px;
  border: 1px solid #ccc;
  margin-bottom: 10px;
}

.card-header {
  background-color: #f0f0f0;
  padding: 10px;
  cursor: move;
}

.card-body {
  padding: 10px;
}

実行すると、カードをドラッグ&ドロップで並び替えることができます。

このコードでは、カードを格納するためのdiv要素に対してSortableを適用しています。

オプションのhandleには’.card-header’を指定し、カードのヘッダー部分をドラッグハンドルにしています。

また、animationオプションを150に設定することで、カードの移動アニメーションをスムーズにしています。

CSSでは、カードのスタイルを定義しています。

カードのヘッダー部分には、背景色を設定し、cursorプロパティでマウスカーソルをつかむアイコンに変更しています。

このようにカード形式のUIにSortable.jsを適用することで、直感的な操作性を実現できます。

タスクの優先順位を変更したり、項目をグループ化したりと、さまざまな用途に応用できるでしょう。

○サンプルコード8:Vue.jsでの利用方法

Vue.jsは、コンポーネントベースのUIを構築するためのJavaScriptフレームワークです。

Sortable.jsをVue.jsと組み合わせることで、リアクティブなドラッグ&ドロップ機能を実装できます。

<div id="app">
  <ul>
    <li v-for="item in items" :key="item.id">
      {{ item.text }}
    </li>
  </ul>
</div>
const Vue = require('vue');
const Sortable = require('sortablejs');

new Vue({
  el: '#app',
  data: {
    items: [
      { id: 1, text: 'りんご' },
      { id: 2, text: 'ばなな' },
      { id: 3, text: 'みかん' },
    ],
  },
  mounted() {
    const el = this.$el.querySelector('ul');
    Sortable.create(el, {
      onUpdate: (evt) => {
        const oldIndex = evt.oldIndex;
        const newIndex = evt.newIndex;
        const item = this.items.splice(oldIndex, 1)[0];
        this.items.splice(newIndex, 0, item);
      },
    });
  },
});

実行すると、リストの項目をドラッグ&ドロップで並び替えると、Vue.jsのリアクティブシステムによって自動的に画面が更新されます。

このコードでは、Vue.jsのマウントオプションを使って、DOMの読み込みが完了した後にSortableを初期化しています。

また、onUpdateイベントを使って、並び替え後の処理を行っています。

具体的には、並び替え前の位置(oldIndex)と並び替え後の位置(newIndex)を取得し、Vue.jsのデータ配列(items)から該当する要素を削除して、新しい位置に挿入し直しています。

これにより、Vue.jsのリアクティブシステムが変更を検知し、自動的に画面を更新してくれます。

このように、Sortable.jsとVue.jsを組み合わせることで、リアクティブなドラッグ&ドロップ機能を簡単に実装できます。

Vue.jsの直感的な操作性とSortable.jsの柔軟さを組み合わせれば、より洗練されたUIを構築できるでしょう。

○サンプルコード9:React での利用方法

Reactは、FacebookによるUIを構築するためのJavaScriptライブラリです。

Sortable.jsをReactと組み合わせることで、宣言的なドラッグ&ドロップ機能を実装できます。

import React, { useRef, useEffect } from 'react';
import { render } from 'react-dom';
import Sortable from 'sortablejs';

const App = () => {
  const listRef = useRef(null);

  useEffect(() => {
    Sortable.create(listRef.current, {
      onEnd: (evt) => {
        const oldIndex = evt.oldIndex;
        const newIndex = evt.newIndex;
        // 並び替え後の処理を行う
      },
    });
  }, []);

  return (
    <ul ref={listRef}>
      <li>りんご</li>
      <li>ばなな</li>
      <li>みかん</li>
    </ul>
  );
};

render(<App />, document.getElementById('root'));

実行すると、リストの項目をドラッグ&ドロップで並び替えることができます。

このコードでは、Reactの関数コンポーネントを使っています。

useRefフックを使って、ul要素への参照を取得し、useEffectフックを使って、コンポーネントのマウント時にSortableを初期化しています。

onEndイベントを使って、並び替え後の処理を行います。

並び替え前の位置(oldIndex)と並び替え後の位置(newIndex)を取得できるので、それを元にReactのstateを更新するなどの処理を行うことができます。

まとめ

Sortable.jsは、ドラッグ&ドロップによるリストの並び替えを簡単に実装できる便利なライブラリです。

シンプルなコードで直感的なUIを実現でき、カスタマイズ性も高いため、さまざまなシーンで活躍します。

基本的な使い方からオプションの活用方法、よくあるエラーの対処法まで、この記事ではSortable.jsの魅力を存分にお伝えできたのではないでしょうか。

これからSortable.jsを使ってみようと思っている方も、すでに使っているけどもっと活用したいと考えている方も、ぜひこの記事を参考にしてみてください。

きっと、魅力的なドラッグ&ドロップインターフェースを実装するためのヒントが見つかるはずです。