【初心者向け】HTMLテーブルにソート機能を追加!コピペOK&JavaScriptだけで簡単並び替えする方法

sortable-table javascript

Webサイトに大量のデータを載せたとき、「表(table)の中身を並び替えできたら、もっと見やすいのに」と思ったことはありませんか?

しかし、いざ自分でソート機能をつけようとすると、「JavaScriptの知識が必要?」「ライブラリって何を使えばいいの?」と迷ってしまう方も多いはずです。特にHTML初心者の方にとって、難しそうに感じる部分かもしれません。

この記事では、HTMLと少しのJavaScriptだけで、しかもコピペで簡単にtableにソート機能を追加できる方法をご紹介します。

さらに、便利なライブラリ(tablesorterやList.js)を使った導入手順や、スマホ対応やデザイン性アップのテクニックまで、やさしく解説していきます。

この記事を読めば、初心者の方でも安心して、データをもっと見やすく整理できるようになります!

この記事でわかること

  • 最低限必要なHTMLとJavaScriptだけでテーブルにソート機能をつける方法
  • th(ヘッダー)をクリックして昇順・降順を切り替える仕組み
  • コピペですぐ使える、シンプルなソートサンプルコード
  • tablesorterとList.jsを使った初心者向けのソート&フィルター機能の導入方法
  • 昇順・降順アイコン(▲▼)を表示するテクニック
  • Bootstrapと組み合わせたテーブルソートの簡単実装法
  • スマホでも崩れないレスポンシブ対応のテーブルソート方法

それでは、早速「HTMLテーブルをもっと使いやすくする」方法を見ていきましょう!

HTML初心者でもできる!tableにソート機能を追加する基本ステップ

Webサイトでテーブル(表)を使うとき、「あれ、この列で並べ替えできたらいいのに…」と思ったことはありませんか?実は、HTMLの表にソート機能を追加するのは、初心者の方でも意外と簡単にできるんです。

この記事では、プログラミング初心者の方でも実装できる、テーブルソート機能の基本的な実装方法をご紹介します。HTMLとJavaScriptの基礎知識があれば十分ですので、ぜひチャレンジしてみてください。

ソートに必要な最低限のHTMLとJavaScriptとは?

まずは、テーブルソートを実装するために最低限必要なHTMLとJavaScriptの知識についてお話しします。

必要なHTML構造

テーブルをソート可能にするためには、正しいHTML構造が重要です。具体的には以下の要素が必要になります:

  • <table> – テーブル全体を定義
  • <thead> – テーブルヘッダー部分を定義
  • <tbody> – テーブル本体(データ部分)を定義
  • <th> – ヘッダーセル(クリックでソートする部分)
  • <tr> – 行
  • <td> – データセル

例えば、次のようなシンプルなHTMLテーブル構造が基本となります:

<table id="myTable">
  <thead>
    <tr>
      <th data-sort="name">名前</th>
      <th data-sort="age">年齢</th>
      <th data-sort="score">得点</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>田中太郎</td>
      <td>28</td>
      <td>85</td>
    </tr>
    <tr>
      <td>鈴木花子</td>
      <td>24</td>
      <td>92</td>
    </tr>
    <!-- その他の行 -->
  </tbody>
</table>

ここでのポイントは、<th>タグにdata-sortなどの属性を追加しておくと、JavaScriptでソート対象の列を特定しやすくなります。

必要なJavaScript知識

ソート機能を実装するためには、次のJavaScriptの基本概念を理解しておくと良いでしょう:

  1. DOM操作 – HTMLの要素を取得・操作する方法
  2. イベントリスナー – クリックなどのユーザーアクションを検出する仕組み
  3. 配列操作 – 特にsort()メソッドを使ったデータの並べ替え
  4. 比較関数 – ソートの順序を決めるためのロジック

例えば、テーブルの行をソートする基本的なJavaScriptのイメージは次のようになります:

// テーブルの行を取得してソートする
const rows = Array.from(document.querySelectorAll('#myTable tbody tr'));
rows.sort((a, b) => {
  const aValue = a.cells[columnIndex].textContent;
  const bValue = b.cells[columnIndex].textContent;
  return aValue.localeCompare(bValue); // 文字列比較の場合
});

// ソートした行をテーブルに再配置
const tbody = document.querySelector('#myTable tbody');
rows.forEach(row => tbody.appendChild(row));

初心者の方には少し難しく見えるかもしれませんが、このコードの基本的な流れは「行を取得→並べ替え→再配置」という3ステップです。これだけで基本的なソート機能が実現できるんです。

ヘッダー(th)クリックで昇順・降順を切り替える仕組み

テーブルソートの基本的な操作性として、ヘッダーをクリックすると昇順・降順が切り替わる機能が便利です。この機能を実装する方法を見ていきましょう。

ソート状態の管理

昇順・降順を切り替えるには、現在のソート状態を管理する必要があります。これには主に2つの方法があります:

変数でソート状態を管理する方法

let sortDirection = 1; // 1=昇順、-1=降順

function toggleSort() {
  sortDirection *= -1; // クリックするたびに反転
  // ソート処理...
}

HTML属性でソート状態を管理する方法

function toggleSort(header) {
  // 現在の状態を取得(なければ昇順から開始)
  const currentDir = header.getAttribute('data-sort-direction') || 'asc';

  // 状態を切り替え
  const newDir = currentDir === 'asc' ? 'desc' : 'asc';
  header.setAttribute('data-sort-direction', newDir);

  // ソート処理...
}

2番目の方法は、状態をHTML要素自体に保持するので、複数の列でソートする場合に便利です。

クリックイベントの設定

ヘッダーをクリックしたときにソートが実行されるように、イベントリスナーを設定します:

// すべてのソート可能なヘッダーに対してクリックイベントを設定
document.querySelectorAll('#myTable th[data-sort]').forEach(header => {
  header.addEventListener('click', function() {
    const columnName = this.getAttribute('data-sort');
    sortTable(columnName, this);
  });
});

データ型に応じたソート処理

テーブルには文字列、数値、日付など様々なデータが含まれます。データ型に応じて正しくソートするには、比較関数を適切に設定する必要があります:

function compareValues(a, b, type) {
  switch(type) {
    case 'number':
      return parseFloat(a) - parseFloat(b);
    case 'date':
      return new Date(a) - new Date(b);
    default: // 文字列
      return a.localeCompare(b, 'ja'); // 日本語対応
  }
}

日本語のテキストを正しくソートするには、localeCompare()'ja'を指定すると良いでしょう。数字が含まれるセルでは、parseFloat()を使って数値に変換してから比較すると自然な並び順になります。

実際に昇順・降順を切り替えるソート処理は、次のようになります:

function sortTable(columnName, header) {
  const table = document.getElementById('myTable');
  const tbody = table.querySelector('tbody');
  const rows = Array.from(tbody.querySelectorAll('tr'));

  // ソート方向を取得・切り替え
  const currentDir = header.getAttribute('data-sort-direction') || 'asc';
  const newDir = currentDir === 'asc' ? 'desc' : 'asc';

  // ヘッダーの状態を更新
  document.querySelectorAll('#myTable th').forEach(th => {
    th.removeAttribute('data-sort-direction');
  });
  header.setAttribute('data-sort-direction', newDir);

  // 列のインデックスを取得
  const columnIndex = Array.from(header.parentNode.children).indexOf(header);

  // データ型を判断(簡易版)
  const dataType = header.getAttribute('data-type') || 'string';

  // ソート処理
  rows.sort((rowA, rowB) => {
    const cellA = rowA.cells[columnIndex].textContent.trim();
    const cellB = rowB.cells[columnIndex].textContent.trim();

    // 昇順or降順に応じて係数を変える
    const direction = newDir === 'asc' ? 1 : -1;

    return direction * compareValues(cellA, cellB, dataType);
  });

  // ソート結果をテーブルに反映
  rows.forEach(row => tbody.appendChild(row));
}

このコードでは、クリックするたびに昇順と降順が切り替わり、現在ソートされている列と方向が視覚的に確認できるようになっています。

コピペOK!超シンプルなテーブルソートのサンプルコード紹介

それでは、実際にコピー&ペーストで使える完全なサンプルコードをご紹介します。このコードは最小限の機能に絞っているので、初心者の方でも理解しやすいはずです。

HTML部分

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>シンプルテーブルソート</title>
  <style>
    table {
      width: 100%;
      border-collapse: collapse;
      margin-bottom: 20px;
    }
    th, td {
      border: 1px solid #ddd;
      padding: 8px;
      text-align: left;
    }
    th {
      background-color: #f2f2f2;
      cursor: pointer;
    }
    th:hover {
      background-color: #ddd;
    }
    th[data-sort-direction="asc"]::after {
      content: " ▲";
      font-size: 0.8em;
    }
    th[data-sort-direction="desc"]::after {
      content: " ▼";
      font-size: 0.8em;
    }
  </style>
</head>
<body>
  <h1>ソート可能なテーブル</h1>
  <table id="sortableTable">
    <thead>
      <tr>
        <th data-sort="string">名前</th>
        <th data-sort="number">年齢</th>
        <th data-sort="number">得点</th>
        <th data-sort="date">登録日</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>田中太郎</td>
        <td>28</td>
        <td>85</td>
        <td>2023-04-15</td>
      </tr>
      <tr>
        <td>鈴木花子</td>
        <td>24</td>
        <td>92</td>
        <td>2023-02-10</td>
      </tr>
      <tr>
        <td>佐藤一郎</td>
        <td>32</td>
        <td>78</td>
        <td>2023-01-05</td>
      </tr>
      <tr>
        <td>山田優子</td>
        <td>22</td>
        <td>95</td>
        <td>2023-05-20</td>
      </tr>
      <tr>
        <td>渡辺健太</td>
        <td>30</td>
        <td>88</td>
        <td>2023-03-12</td>
      </tr>
    </tbody>
  </table>

  <script>
    // ここにJavaScriptコードが入ります(次のセクションで紹介)
  </script>
</body>
</html>

JavaScript部分

document.addEventListener('DOMContentLoaded', function() {
  // ソート可能な列にイベントリスナーを設定
  document.querySelectorAll('#sortableTable th[data-sort]').forEach(header => {
    header.addEventListener('click', function() {
      sortTable(this);
    });
  });

  // テーブルソート関数
  function sortTable(header) {
    const table = document.getElementById('sortableTable');
    const tbody = table.querySelector('tbody');
    const rows = Array.from(tbody.querySelectorAll('tr'));

    // 列のインデックスを取得
    const columnIndex = Array.from(header.parentNode.children).indexOf(header);

    // データ型を取得
    const dataType = header.getAttribute('data-sort');

    // 現在のソート方向を取得
    const currentDir = header.getAttribute('data-sort-direction') || 'asc';
    const newDir = currentDir === 'asc' ? 'desc' : 'asc';

    // 他の列のソート状態をリセット
    document.querySelectorAll('#sortableTable th').forEach(th => {
      th.removeAttribute('data-sort-direction');
    });

    // 現在の列のソート方向を設定
    header.setAttribute('data-sort-direction', newDir);

    // 行をソート
    rows.sort((rowA, rowB) => {
      let a = rowA.cells[columnIndex].textContent.trim();
      let b = rowB.cells[columnIndex].textContent.trim();

      // データ型に応じた比較
      if (dataType === 'number') {
        return (newDir === 'asc' ? 1 : -1) * (parseFloat(a) - parseFloat(b));
      } else if (dataType === 'date') {
        return (newDir === 'asc' ? 1 : -1) * (new Date(a) - new Date(b));
      } else {
        // 文字列比較(日本語対応)
        return (newDir === 'asc' ? 1 : -1) * a.localeCompare(b, 'ja');
      }
    });

    // ソートした行をテーブルに再配置
    rows.forEach(row => tbody.appendChild(row));
  }
});

このコードの特徴と使い方

このサンプルコードには、以下のような特徴があります:

  1. 簡単に導入できる:HTMLとCSSとJavaScriptをコピーするだけで動作します
  2. 複数のデータ型に対応:文字列、数値、日付のソートに対応しています
  3. 視覚的フィードバック:昇順・降順を示す矢印(▲▼)が自動的に表示されます
  4. 日本語対応localeCompare()を使って日本語の正しい並び替えができます

使い方は非常に簡単です:

①HTMLテーブルの<th>タグにdata-sort属性を追加し、データ型を指定します

  • data-sort="string" – 文字列
  • data-sort="number" – 数値
  • data-sort="date" – 日付

②必要に応じてCSSでテーブルのスタイルをカスタマイズします

③JavaScriptコードをそのまま使用するか、必要に応じて調整します

これだけで、どんなテーブルにもソート機能を追加できます。例えば、商品一覧や会員リスト、スコアボードなど様々な用途に活用できるでしょう。

ウェブサイトの利便性を大きく向上させる割に、実装は数十行程度のコードで済むため、コストパフォーマンスが非常に高い機能だと言えます。HTMLの基本的な知識があれば、このサンプルコードをベースに自分のウェブサイトに合わせてカスタマイズしていくことも簡単です。

たった数行で実現!おすすめソートライブラリ【tablesorter・List.js】

HTMLテーブルにソート機能を実装する方法として、前のセクションではJavaScriptを使った基本的な実装方法をご紹介しました。しかし、もっと簡単かつ高機能な方法もあります。それが「ソートライブラリ」の活用です。

ライブラリを使えば、わずか数行のコードでプロフェッショナルなテーブルソート機能を実現できます。このセクションでは、初心者の方にもおすすめのテーブルソートライブラリをご紹介し、その導入方法を解説します。

tablesorterをCDNで簡単導入する方法【初心者向け手順】

「tablesorter」は、jQueryプラグインとして提供されている人気のテーブルソートライブラリです。10年以上の歴史があり、安定性と機能性に定評があります。

tablesorterの主な特徴

  • 様々なデータ型(文字列、数値、日付など)の自動認識
  • 複雑なテーブル構造にも対応
  • カスタマイズの自由度が高い
  • 豊富なドキュメントとサンプル
  • 日本語を含む多言語対応

CDNでtablesorterを導入する手順

CDN(Content Delivery Network)を使えば、サーバーにファイルをアップロードすることなく、簡単にライブラリを利用できます。以下は、tablesorterをCDNで導入する具体的な手順です。

cdnjs - The #1 free and open source CDN built to make life easier for developers
Simple. Fast. Reliable. Content delivery at its finest. cdnjs is a free and open-source CDN service trusted by over 12.5% of all websites, serving over 200 bill...
1. HTML内にjQueryとtablesorterのCDNリンクを追加

HTMLの<head>タグ内、または</body>タグの直前に次のコードを追加します:

<!-- jQuery -->
<script src="<https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js>"></script>

<!-- tablesorter -->
<script src="<https://cdnjs.cloudflare.com/ajax/libs/jquery.tablesorter/2.31.3/js/jquery.tablesorter.min.js>"></script>
<link rel="stylesheet" href="<https://cdnjs.cloudflare.com/ajax/libs/jquery.tablesorter/2.31.3/css/theme.default.min.css>">
2. テーブルに適切なクラスとIDを設定

tablesorterを適用するテーブルにIDを設定します:

<table id="myTable" class="tablesorter">
  <thead>
    <tr>
      <th>名前</th>
      <th>年齢</th>
      <th>得点</th>
      <th>登録日</th>
    </tr>
  </thead>
  <tbody>
    <!-- テーブルの内容 -->
  </tbody>
</table>

ポイントは、class="tablesorter"を追加することです。これによりデフォルトのスタイルが適用されます。

3. JavaScriptでtablesorterを初期化

HTMLの末尾または別のJavaScriptファイルに以下のコードを追加します:

$(document).ready(function() {
  $("#myTable").tablesorter();
});

たったこれだけで、テーブルの各列をクリックするとソート機能が動作するようになります。初期化時にオプションを追加することで、さらに細かな設定も可能です:

$("#myTable").tablesorter({
  // デフォルトのソート列を指定(0から始まる列番号)
  sortList: [[0, 0]],  // 最初の列を昇順でソート

  // ウィジェットを有効化
  widgets: ['zebra', 'filter'],

  // 日本語対応
  textExtraction: function(node) {
    return node.textContent || node.innerText;
  },

  // ヘッダーのCSSクラス
  cssHeader: "tablesorter-header",

  // 昇順・降順のCSSクラス
  cssAsc: "tablesorter-headerSortUp",
  cssDesc: "tablesorter-headerSortDown"
});

tablesorterで日付や数値を正しくソートするコツ

tablesorterは通常、データ型を自動的に判断してソートしますが、特定のフォーマットの日付や数値を正しく認識させるには、追加の設定が必要な場合があります。

日本語形式の日付(yyyy年mm月dd日)をソートする

$.tablesorter.addParser({
  id: 'jpdate',
  is: function(s) {
    return /\\d{4}年\\d{1,2}月\\d{1,2}日/.test(s);
  },
  format: function(s) {
    // 「2023年4月1日」→「2023/04/01」に変換
    s = s.replace(/(\\d{4})年(\\d{1,2})月(\\d{1,2})日/, function(match, y, m, d) {
      return y + '/' + ('0' + m).slice(-2) + '/' + ('0' + d).slice(-2);
    });
    return new Date(s).getTime();
  },
  type: 'numeric'
});

// パーサーを特定の列に適用
$("#myTable").tablesorter({
  headers: {
    3: { sorter: 'jpdate' } // 4列目(0始まり)に適用
  }
});

通貨形式(¥1,000など)をソートする

$.tablesorter.addParser({
  id: 'currency',
  is: function(s) {
    return /^[¥$€£]/.test(s);
  },
  format: function(s) {
    // 「¥1,000」→「1000」に変換
    return s.replace(/[¥$€£,]/g, '');
  },
  type: 'numeric'
});

// 使用例
$("#myTable").tablesorter({
  headers: {
    2: { sorter: 'currency' } // 3列目に適用
  }
});

tablesorterのよくあるエラーと解決法

初めて使う方がつまずきやすいポイントとその解決策をご紹介します:

  1. 「$ is not defined」エラー
    • 原因:jQueryが読み込まれていない
    • 解決策:jQueryのCDNリンクが正しく設定されているか確認
  2. ソートが動作しない
    • 原因:tablesorterの初期化コードが実行されていない
    • 解決策:$(document).ready()内に初期化コードがあるか確認
  3. 特定の列だけソートされない
    • 原因:データ形式が認識されていない
    • 解決策:カスタムパーサーを定義するか、headersオプションでデータタイプを指定
  4. 日本語が正しくソートされない
    • 原因:デフォルトの比較方法が英語向け
    • 解決策:textExtractionオプションを設定し、textContentまたはinnerTextを使用

List.jsでフィルター&ソート機能を一括実装するやり方

tablesorterが素晴らしいライブラリである一方、jQueryに依存している点がデメリットとなることもあります。そこでおすすめなのが「List.js」です。List.jsはjQueryに依存せず、さらにソート機能に加えてフィルター機能も同時に実装できる軽量ライブラリです。

List.jsの主な特徴

  • jQueryが不要(純粋なJavaScript)
  • ファイルサイズが小さく(約7KB)、読み込みが早い
  • ソート・検索・ページネーション機能を提供
  • テーブルだけでなくリストやカードにも対応
  • 簡単なAPIで拡張可能

List.jsの基本的な導入手順

1. CDNでList.jsを読み込む
<script src="<https://cdnjs.cloudflare.com/ajax/libs/list.js/2.3.1/list.min.js>"></script>
2. HTMLにList.js用の構造を設定
<div id="users">
  <input class="search" placeholder="検索" />

  <table>
    <thead>
      <tr>
        <th class="sort" data-sort="name">名前</th>
        <th class="sort" data-sort="age">年齢</th>
        <th class="sort" data-sort="score">得点</th>
      </tr>
    </thead>
    <tbody class="list">
      <tr>
        <td class="name">田中太郎</td>
        <td class="age">28</td>
        <td class="score">85</td>
      </tr>
      <tr>
        <td class="name">鈴木花子</td>
        <td class="age">24</td>
        <td class="score">92</td>
      </tr>
      <!-- その他の行 -->
    </tbody>
  </table>
</div>

ポイントは以下の通りです:

  • 全体を包む要素(id="users")が必要
  • ソート可能な列のヘッダーにclass="sort"data-sort="項目名"を設定
  • tbody要素にclass="list"を設定
  • 各データセルに対応するclass="項目名"を設定
  • 検索ボックスにはclass="search"を設定
3. JavaScriptでList.jsを初期化
document.addEventListener('DOMContentLoaded', function() {
  var options = {
    valueNames: ['name', 'age', 'score']
  };

  var userList = new List('users', options);
});

valueNamesには、ソート対象となる各セルのクラス名を指定します。

List.jsでフィルターとソートを組み合わせる方法

List.jsの便利な点は、検索機能とソート機能を簡単に組み合わせられることです。検索ボックスを追加するだけで、自動的にテーブル内のデータをリアルタイムでフィルタリングしてくれます。

<div id="users">
  <!-- 検索ボックス -->
  <div class="search-box">
    <input class="search" placeholder="名前やデータで検索..." />
    <button class="sort" data-sort="name">名前でソート</button>
    <button class="sort" data-sort="score">得点でソート</button>
  </div>

  <!-- テーブル本体 -->
  <table>
    <!-- 前述と同じ構造 -->
  </table>
</div>

この例では、テキスト入力による検索に加えて、ボタンクリックでもソートができるようになっています。

List.jsで数値と日付を正しくソートする設定

List.jsでも、データ型に応じたソート方法を指定できます:

var options = {
  valueNames: [
    'name',
    { name: 'age', attr: 'data-age' },
    { name: 'score', attr: 'data-score' },
    { name: 'date', attr: 'data-date' }
  ],
  // ソート関数をカスタマイズ
  sortFunction: function(itemA, itemB, options) {
    if (options.valueName === 'date') {
      // 日付のソート
      return new Date(itemA.values().date) - new Date(itemB.values().date);
    } else {
      // デフォルトのソート
      return itemA._values[options.valueName].localeCompare(itemB._values[options.valueName], 'ja');
    }
  }
};

var userList = new List('users', options);

この例では、HTML要素にdata-agedata-scoreなどの属性でソート用の値を保持し、それを使ってソートしています。日付については特別な処理を追加しています。

ソースコードを自分仕様にカスタマイズするポイントとコツ

ライブラリを導入したら、次はそれを自分のウェブサイトに合わせてカスタマイズしていきましょう。ここでは、両ライブラリに共通するカスタマイズのポイントをいくつかご紹介します。

スタイルのカスタマイズ

テーブルの見た目は、CSSを使って自由にカスタマイズできます。例えば:

/* テーブル全体のスタイル */
table.tablesorter {
  width: 100%;
  border-collapse: collapse;
  font-family: 'Noto Sans JP', sans-serif;
  margin-bottom: 1.5em;
}

/* ヘッダーのスタイル */
table.tablesorter thead th {
  background-color: #f5f5f5;
  border-bottom: 2px solid #ddd;
  padding: 12px 8px;
  cursor: pointer;
  position: relative;
}

/* ソート中の列のスタイル */
table.tablesorter thead th.tablesorter-headerSortUp,
table.tablesorter thead th.tablesorter-headerSortDown {
  background-color: #e9e9e9;
}

/* ソートアイコンのスタイル */
table.tablesorter thead th.tablesorter-headerSortUp::after {
  content: "▲";
  font-size: 0.8em;
  margin-left: 5px;
  color: #333;
}

table.tablesorter thead th.tablesorter-headerSortDown::after {
  content: "▼";
  font-size: 0.8em;
  margin-left: 5px;
  color: #333;
}

/* 交互に色分けする(ゼブラストライプ) */
table.tablesorter tbody tr:nth-child(even) {
  background-color: #f9f9f9;
}

/* マウスホバー時のスタイル */
table.tablesorter tbody tr:hover {
  background-color: #f0f0f0;
}

ソート時のアニメーション効果を追加

ソート操作を視覚的に分かりやすくするために、アニメーション効果を追加することもできます:

/* ソート時のトランジション効果 */
table.tablesorter tbody tr {
  transition: background-color 0.2s ease;
}

tablesorterの場合は、jQuery UIを使ってアニメーションを追加することもできます:

$("#myTable").tablesorter({
  // ソート中にクラスを追加
  cssChildRow: "tablesorter-childRow",

  // Widget機能を使用
  widgets: ['zebra'],

  // Widget初期化時の処理
  initialized: function(table) {
    // 表示アニメーション
    $(table).find('tbody tr').hide().fadeIn(800);
  }
});

// ソート完了時にアニメーションを追加
$("#myTable").on('sortEnd', function() {
  $(this).find('tbody tr').hide().fadeIn(500);
});

ソート不可の列を設定する方法

特定の列をソート対象から除外したい場合の設定も簡単です:

tablesorterの場合
$("#myTable").tablesorter({
  headers: {
    0: { sorter: false },  // 最初の列はソート不可
    2: { sorter: false }   // 3列目もソート不可
  }
});
List.jsの場合

ソート不可にしたい列のヘッダーから、class="sort"data-sort属性を削除するだけです。

デフォルトのソート設定を変更する

ページ読み込み時に、特定の列で自動的にソートされるよう設定することもできます:

tablesorterの場合
$("#myTable").tablesorter({
  // 初期ソート設定
  sortList: [[1, 1]]  // 2列目(インデックス1)を降順(1)でソート
});
List.jsの場合
var userList = new List('users', options);

// 初期化後に特定の列でソート
userList.sort('score', { order: 'desc' });  // scoreで降順ソート

これらのカスタマイズを組み合わせることで、自分のサイトのデザインや用途に最適なテーブルソート機能を実現できます。初心者の方でも、少しずつ機能を追加していくことで、徐々に高度なテーブルを作成していけるでしょう。

tablesorterとList.jsのどちらを選ぶかは、サイトの既存の構成やニーズによって異なります。jQueryを既に使っているサイトではtablesorterが、軽量さを重視する場合やフィルター機能も必要な場合はList.jsが適しているでしょう。どちらも初心者の方でも導入しやすいライブラリなので、ぜひお試しください。

もっと便利に!スマホ対応・アイコン表示・Bootstrap連携テクニック

ここまでは、テーブルソートの基本的な実装方法とライブラリの導入方法をご紹介してきました。このセクションでは、さらに一歩進んで、テーブルソート機能をより使いやすく、見た目も美しくするための応用テクニックをご紹介します。

特に、現代のウェブサイトには欠かせないスマホ対応や、直感的な操作を可能にするアイコン表示、そして人気のCSSフレームワーク「Bootstrap」との連携方法など、実践的なテクニックを解説していきます。これらを活用することで、プロフェッショナルなテーブルソート機能を実現できるでしょう。

Bootstrap
パワフルで拡張性の高い、機能満載のフロントエンドツールキットです。Sassでビルドしてカスタマイズし、あらかじめ用意されたグリッドシステムとコンポーネントを利用し、強力なJavaScriptプラグインでプロジェクトに命を吹き込むことができます。

昇順・降順アイコン(▲▼)を自動で表示する方法

テーブルをソートする際、現在どの列がどの順序(昇順・降順)でソートされているかを視覚的に表示することは、ユーザビリティの観点から非常に重要です。ここでは、ソート状態を示すアイコンを表示するための様々な方法をご紹介します。

CSSのみでアイコンを表示する方法

もっともシンプルな方法は、CSSの疑似要素(::after、::before)を使ってアイコンを表示する方法です。

/* ソート可能な列のスタイル */
th.sortable {
  position: relative;
  cursor: pointer;
  padding-right: 20px; /* アイコン用のスペース確保 */
}

/* ソート可能な列にホバーした時のスタイル */
th.sortable:hover {
  background-color: #f5f5f5;
}

/* 未ソート状態の列に薄いアイコンを表示 */
th.sortable::after {
  content: "⇅";
  position: absolute;
  right: 5px;
  color: #ccc;
  font-size: 0.8em;
}

/* 昇順ソート時のアイコン */
th.sort-asc::after {
  content: "▲";
  color: #333;
}

/* 降順ソート時のアイコン */
th.sort-desc::after {
  content: "▼";
  color: #333;
}

JavaScriptでソート状態に応じてクラスを切り替えるコードも必要です:

// ヘッダーのクリックイベント
document.querySelectorAll('th.sortable').forEach(header => {
  header.addEventListener('click', function() {
    // 現在のソート状態を取得
    const isSortAsc = this.classList.contains('sort-asc');
    const isSortDesc = this.classList.contains('sort-desc');

    // すべてのヘッダーからソートクラスを削除
    document.querySelectorAll('th.sortable').forEach(th => {
      th.classList.remove('sort-asc', 'sort-desc');
    });

    // クリックしたヘッダーのソート状態を切り替え
    if (!isSortAsc && !isSortDesc) {
      this.classList.add('sort-asc'); // 初回クリック時は昇順
    } else if (isSortAsc) {
      this.classList.add('sort-desc'); // 昇順→降順
    } else {
      this.classList.add('sort-asc'); // 降順→昇順
    }

    // ここでソート処理を実行
    // ...
  });
});

Font Awesomeを使ったアイコン表示

より洗練されたアイコンを使いたい場合は、Font Awesomeなどのアイコンフォントを活用する方法もあります

Font Awesome
The internet's icon library + toolkit. Used by millions of designers, devs, & content creators. Open-source. Always free. Always awesome.
<!-- Font Awesome CDN -->
<link rel="stylesheet" href="<https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css>">
/* ソート可能な列のスタイル */
th.sortable::after {
  font-family: "Font Awesome 6 Free";
  font-weight: 900;
  margin-left: 5px;
  color: #aaa;
}

/* 未ソート状態 */
th.sortable::after {
  content: "\\f0dc"; /* sort icon */
}

/* 昇順ソート時 */
th.sort-asc::after {
  content: "\\f0de"; /* sort-up icon */
  color: #333;
}

/* 降順ソート時 */
th.sort-desc::after {
  content: "\\f0dd"; /* sort-down icon */
  color: #333;
}

Font Awesomeを使うと、より洗練された見た目のアイコンを表示でき、様々なデザインとも調和しやすくなります。

アニメーションを追加してUX向上

ソート状態の変化をよりわかりやすくするため、アイコンにアニメーションを追加するのも効果的です:

/* アイコンのトランジション設定 */
th.sortable::after {
  transition: transform 0.2s ease, color 0.2s ease;
}

/* ホバー時のエフェクト */
th.sortable:hover::after {
  transform: scale(1.2);
}

/* ソート切り替え時のアニメーション */
@keyframes sortIndicator {
  0% { transform: translateY(-5px); opacity: 0; }
  100% { transform: translateY(0); opacity: 1; }
}

th.sort-asc::after,
th.sort-desc::after {
  animation: sortIndicator 0.3s ease forwards;
}

このようなアニメーションを追加することで、ユーザーの操作に対する視覚的なフィードバックが強化され、使いやすさが向上します。

ライブラリとの連携

前のセクションで紹介したライブラリを使う場合も、アイコン表示をカスタマイズできます:

tablesorterの場合
$("#myTable").tablesorter({
  // アイコンのクラスをカスタマイズ
  cssIcon: 'tablesorter-icon',
  cssIconAsc: 'fa fa-chevron-up',
  cssIconDesc: 'fa fa-chevron-down',

  // アイコンのHTML構造をカスタマイズ
  headerTemplate: '{content} <span class="{icon}"></span>'
});
List.jsの場合

List.jsでは、HTMLを直接カスタマイズします:

<th class="sort" data-sort="name">
  名前 <i class="sort-icon"></i>
</th>
// ソートイベント時にアイコンを更新
userList.on('sortStart', function() {
  // 現在のソート状態を取得
  const sort = userList.sort.order;
  const column = userList.sort.valueName;

  // アイコンをリセット
  document.querySelectorAll('.sort-icon').forEach(icon => {
    icon.className = 'sort-icon';
  });

  // ソート中の列のアイコンを更新
  const th = document.querySelector(`th[data-sort="${column}"] .sort-icon`);
  if (th) {
    th.classList.add(sort === 'asc' ? 'fa fa-chevron-up' : 'fa fa-chevron-down');
  }
});

アイコンの表示方法は様々ですが、いずれの方法でも「現在のソート状態がユーザーに一目でわかる」ことが重要です。特に情報量の多いテーブルでは、この視覚的なフィードバックが操作性を大きく左右します。

Bootstrapのtableに自然にソート機能を組み込む手順

Bootstrapは現在もっとも人気のあるCSSフレームワークの一つで、多くのウェブサイトで使われています。Bootstrapのテーブルスタイルを活かしながら、ソート機能を自然に組み込む方法を見ていきましょう。

Bootstrapテーブルの基本構造

まずは、Bootstrapのテーブル基本構造を確認しておきましょう:

<table class="table table-striped table-hover">
  <thead>
    <tr>
      <th scope="col">名前</th>
      <th scope="col">年齢</th>
      <th scope="col">得点</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>田中太郎</td>
      <td>28</td>
      <td>85</td>
    </tr>
    <!-- その他の行 -->
  </tbody>
</table>

方法1:tablesorterとBootstrapの統合

tablesorterとBootstrapを組み合わせるには、専用のテーマを使うのが便利です:

<!-- Bootstrap CSS -->
<link href="<https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css>" rel="stylesheet">

<!-- jQuery -->
<script src="<https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js>"></script>

<!-- tablesorter + Bootstrap テーマ -->
<script src="<https://cdnjs.cloudflare.com/ajax/libs/jquery.tablesorter/2.31.3/js/jquery.tablesorter.min.js>"></script>
<script src="<https://cdnjs.cloudflare.com/ajax/libs/jquery.tablesorter/2.31.3/js/jquery.tablesorter.widgets.min.js>"></script>
<link rel="stylesheet" href="<https://cdnjs.cloudflare.com/ajax/libs/jquery.tablesorter/2.31.3/css/theme.bootstrap_4.min.css>">

初期化コード:

$(document).ready(function() {
  $(".table").tablesorter({
    theme: 'bootstrap',
    widthFixed: true,
    headerTemplate: '{content} {icon}',
    widgets: ['zebra', 'columns', 'uitheme'],
    widgetOptions: {
      zebra: ["even", "odd"],
      columns: ["primary", "secondary", "tertiary"],
      uitheme: 'bootstrap'
    }
  });
});

方法2:List.jsとBootstrapの統合

List.jsはフレームワークに依存しないので、Bootstrapと簡単に組み合わせることができます:

<!-- Bootstrap CSS -->
<link href="<https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css>" rel="stylesheet">

<!-- List.js -->
<script src="<https://cdnjs.cloudflare.com/ajax/libs/list.js/2.3.1/list.min.js>"></script>

<div id="users">
  <div class="input-group mb-3">
    <span class="input-group-text">検索</span>
    <input type="text" class="form-control search" placeholder="名前や得点で検索...">
  </div>

  <table class="table table-striped table-hover">
    <thead>
      <tr>
        <th scope="col" class="sort" data-sort="name">名前 <i class="sort-icon"></i></th>
        <th scope="col" class="sort" data-sort="age">年齢 <i class="sort-icon"></i></th>
        <th scope="col" class="sort" data-sort="score">得点 <i class="sort-icon"></i></th>
      </tr>
    </thead>
    <tbody class="list">
      <!-- テーブルの行 -->
    </tbody>
  </table>
</div>

List.jsの初期化:

document.addEventListener('DOMContentLoaded', function() {
  var options = {
    valueNames: ['name', 'age', 'score'],
    // Bootstrapのスタイルを邪魔しないソート用CSS
    listClass: 'list',
    sortClass: 'sort'
  };

  var userList = new List('users', options);

  // ソートアイコンの更新
  function updateIcons() {
    document.querySelectorAll('.sort-icon').forEach(icon => {
      icon.className = 'sort-icon';
    });

    if (userList.sort.order) {
      const icon = document.querySelector(`th[data-sort="${userList.sort.valueName}"] .sort-icon`);
      icon.className = userList.sort.order === 'asc' ?
        'sort-icon bi bi-caret-up-fill' :
        'sort-icon bi bi-caret-down-fill';
    }
  }

  userList.on('sortStart', updateIcons);

  // 初期ソート
  userList.sort('name', { order: 'asc' });
  updateIcons();
});

Bootstrapのカード内にソート可能テーブルを配置

よりリッチなUIを作るために、Bootstrapのカードコンポーネント内にテーブルを配置することもできます:

<div class="card">
  <div class="card-header">
    <h5 class="card-title mb-0">ユーザー一覧</h5>
  </div>
  <div class="card-body">
    <div class="input-group mb-3">
      <span class="input-group-text">検索</span>
      <input type="text" class="form-control search" placeholder="検索...">
    </div>
  </div>
  <table class="table table-striped mb-0">
    <!-- テーブルの内容 -->
  </table>
  <div class="card-footer">
    <nav aria-label="Table navigation">
      <ul class="pagination justify-content-end mb-0">
        <!-- ページネーション -->
      </ul>
    </nav>
  </div>
</div>

このように、Bootstrapのコンポーネントとテーブルソート機能を組み合わせることで、見た目も機能も洗練されたUIを簡単に作成できます。

Bootstrapのレスポンシブユーティリティとの連携

Bootstrapのtable-responsiveクラスを使うと、スマホ表示にも対応できます:

<div class="table-responsive">
  <table class="table tablesorter">
    <!-- テーブルの内容 -->
  </table>
</div>

また、特定の画面サイズごとにレスポンシブ動作を変えることもできます:

<!-- 小さな画面ではスクロール、大きな画面では全て表示 -->
<div class="table-responsive-sm">
  <table class="table">
    <!-- テーブルの内容 -->
  </table>
</div>

スマホでも崩れない!レスポンシブ対応テーブルソートの作り方

スマートフォンでの閲覧が増えている現代、テーブルのスマホ対応は非常に重要です。しかし、テーブルは横幅が広くなりがちなため、スマホ画面では表示が崩れやすい問題があります。ここでは、ソート機能を維持しながらスマホでも見やすいテーブルを作る方法をご紹介します。

基本的なレスポンシブテーブルの実装方法

方法1:横スクロール方式

もっともシンプルな方法は、テーブル全体を横スクロール可能にする方法です:

.table-container {
  width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch; /* iOSでのスムーズスクロール */
}
<div class="table-container">
  <table id="myTable">
    <!-- テーブルの内容 -->
  </table>
</div>

この方法はシンプルですが、ユーザーが横スクロールしないと全ての列を見られないというデメリットがあります。

方法2:カード形式への変換

小さな画面では、テーブルの各行をカード形式で表示する方法もあります:

@media (max-width: 767px) {
  /* テーブルのヘッダーを非表示 */
  #myTable thead {
    display: none;
  }

  /* 各行をブロック要素として表示 */
  #myTable tbody tr {
    display: block;
    margin-bottom: 1rem;
    border: 1px solid #ddd;
    border-radius: 5px;
    padding: 0.5rem;
  }

  /* 各セルをブロック要素として表示 */
  #myTable tbody td {
    display: block;
    text-align: right;
    padding: 0.5rem;
    position: relative;
  }

  /* セルの前にヘッダーテキストを表示 */
  #myTable tbody td:before {
    content: attr(data-label);
    position: absolute;
    left: 0.5rem;
    font-weight: bold;
  }
}

HTMLでは、各セルにdata-label属性を追加します:

<tr>
  <td data-label="名前">田中太郎</td>
  <td data-label="年齢">28</td>
  <td data-label="得点">85</td>
</tr>

この方法を使うと、小さな画面ではテーブルが縦長のカード形式に変換され、各データの前にヘッダー名が表示されます。

方法3:重要な列だけを表示

画面サイズに応じて、重要度の低い列を非表示にする方法もあります:

@media (max-width: 767px) {
  .table .mobile-hide {
    display: none;
  }
}
<table class="table">
  <thead>
    <tr>
      <th>名前</th>
      <th>得点</th>
      <th class="mobile-hide">年齢</th>
      <th class="mobile-hide">登録日</th>
    </tr>
  </thead>
  <tbody>
    <!-- テーブルの内容 -->
  </tbody>
</table>

この方法は単純ですが、一部の情報がスマホでは見られなくなるため、情報の優先度を慎重に検討する必要があります。

レスポンシブテーブルとソート機能の連携

レスポンシブ対応とソート機能を組み合わせる際の注意点とテクニックをご紹介します:

カード形式の場合のソート維持

カード形式に変換しても、ソートは引き続き機能します。ただし、ソート対象の列が視覚的にわかりにくくなるため、追加の工夫が必要です:

// スマホ表示時のソート操作UI
function createMobileSortControls() {
  if (window.innerWidth <= 767) {
    const sortControls = document.createElement('div');
    sortControls.className = 'mobile-sort-controls';

    sortControls.innerHTML = `
      <div class="form-group">
        <label for="sort-select">並び替え:</label>
        <select id="sort-select" class="form-control">
          <option value="name-asc">名前 (昇順)</option>
          <option value="name-desc">名前 (降順)</option>
          <option value="score-asc">得点 (低→高)</option>
          <option value="score-desc">得点 (高→低)</option>
        </select>
      </div>
    `;

    document.querySelector('#table-container').prepend(sortControls);

    // セレクト変更時のイベント
    document.querySelector('#sort-select').addEventListener('change', function() {
      const [column, direction] = this.value.split('-');
      // ソート処理を実行
      // ...
    });
  }
}

// ウィンドウサイズ変更時に再チェック
window.addEventListener('resize', createMobileSortControls);
createMobileSortControls();
tablesorterのレスポンシブ対応

tablesorterを使う場合は、専用のウィジェットを活用できます:

$("#myTable").tablesorter({
  theme: 'bootstrap',
  widgets: ['zebra', 'columns', 'uitheme', 'resizable'],
  widgetOptions: {
    // レスポンシブ対応設定
    resizable: true,
    resizable_widths: ['10%', '20%', '50%', '20%']
  }
});

List.jsのカード表示対応

List.jsの場合、表示形式に応じてテンプレートを切り替えることもできます:

var options = {
  valueNames: ['name', 'age', 'score'],
  // 通常表示用テンプレート
  item: '<tr><td class="name"></td><td class="age"></td><td class="score"></td></tr>'
};

var userList = new List('users', options);

// スマホ表示時にテンプレートを切り替え
function updateTemplate() {
  if (window.innerWidth <= 767) {
    userList.templateEngineOverride = {
      compile: function(data) {
        return `
          <div class="card mb-2">
            <div class="card-body">
              <h5 class="card-title name">${data.name}</h5>
              <div class="d-flex justify-content-between">
                <span>年齢: <span class="age">${data.age}</span>歳</span>
                <span>得点: <span class="score">${data.score}</span>点</span>
              </div>
            </div>
          </div>
        `;
      }
    };
  } else {
    userList.templateEngineOverride = null; // デフォルトに戻す
  }

  userList.update(); // リストを更新
}

window.addEventListener('resize', updateTemplate);
updateTemplate();

スマホ最適化のためのその他のテクニック

タッチ操作の最適化

スマホではタッチ操作が主体となるため、クリックターゲットを大きめにすると操作しやすくなります:

@media (max-width: 767px) {
  #myTable th,
  .mobile-sort-controls select,
  .mobile-sort-controls button {
    padding: 10px;
    min-height: 44px; /* Appleの推奨タッチターゲットサイズ */
  }
}
ピンチズーム対応

スマホでテーブルを見る際に、ピンチズームでの拡大・縮小を許可するのも重要です:

<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
フォントサイズの最適化

スマホ画面ではフォントサイズを少し大きめにして読みやすくします:

@media (max-width: 767px) {
  #myTable {
    font-size: 1rem;
  }

  #myTable th {
    font-size: 1.1rem;
  }
}

これらのテクニックを組み合わせることで、PC・タブレット・スマホなど、あらゆる画面サイズで使いやすいテーブルソート機能を実装できます。特に情報量の多いテーブルでは、スマホ対応を念入りに行うことで、ユーザー体験が大きく向上するでしょう。

レスポンシブデザインは一度実装したら終わりではなく、実際にさまざまなデバイスでテストし、必要に応じて調整していくことが大切です。ぜひ、これらのテクニックを活用して、どのデバイスからでも快適に使えるテーブルソート機能を実装してみてください。

まとめ

HTMLテーブルにソート機能を追加することは、初心者の方でも適切なステップとツールを使えば実現できる素晴らしい機能強化です。この記事を通して、シンプルなコードから便利なライブラリ、さらには応用テクニックまで幅広く解説してきました。

重要ポイント

  • テーブルソートには基本的なHTML構造(thead、tbody、thの適切な使用)が重要
  • JavaScriptでのソート機能実装は、クリックイベントの設定とソートロジックの組み合わせが基本
  • 初心者の方は既存のライブラリ(tablesorterやList.js)の活用がおすすめ
  • カスタマイズには各ライブラリのドキュメントを参照しながら少しずつ変更していくのが効果的

テーブルソートは単にデータを並べ替えるだけでなく、ユーザーの利便性を大きく向上させる機能です。初めは複雑に感じるかもしれませんが、この記事で紹介したステップを一つずつ試していくことで、必ず実装できるようになります。また、基本を理解したら、フィルター機能やレスポンシブ対応など、さらに高度な機能も取り入れていくことができるでしょう。

テーブルソートの実装を通じて、HTMLとJavaScriptの連携についての理解も深まります。ぜひ実際にコードを書いて試してみて、ご自身のWebサイトやアプリケーションを便利で使いやすいものに進化させてください。困ったときは、この記事を参考にしながら、一歩ずつ進めていきましょう!

新しいページトップボタンの処理の書き方。【CSS】scroll-behaviorと【JS】scrollIntoViewを使ったスムーズスクロール
WEBサイトの定番部品の「ページトップへ戻るボタン」。だいたいのWEBサイト、ランディングページ(LP)で必要なので使い回している人も少なくないはずです。jQueryのanimateを利用している人、そのコードもう古いかもしれません。IE11がサポート外になった今、もっと簡単な新しいコードで書いていきましょう。ページ内...
タイトルとURLをコピーしました