JSライブラリ

select要素内のoption要素にCSSを当てて、キーボード操作も可能にする(Tom Select)

select要素内にあるoption要素には、デザインを再現するほどのCSSを当てることが出来ません。
ですのでoption要素にまでデザインの指定がある場合、select・option要素に似せたHTMLやCSS、JSで似た機能を作る必要がありました。

今回紹介する【Tom Select】は、
select要素やoption要素のままCSSでデザイン再現することが出来るJSライブラリです。
キーボード操作にも対応していて非常に便利なのでご紹介します。

目次

実装例

※この実装例ではTom SelectのJSとCSSを読み込ませた上で、作成しています。
(使用画像はテスト用です。デザインセンスの無さはお察しください。)

See the Pen selectBox_CSS_keyboard by Masayuki / ウェブ制作者 (@pazfinder) on CodePen.

JSライブラリ【Tom Select】とは

フレームワークに依存しない、軽量 (~16kb gzip 圧縮) の <select> UI コントロールです。
jQuery からの分離、機能の拡張、問題のバックログへの対処という主な目的で 、元となるselectize.js から派生して作られたようです。

簡単に説明すると、プルダウン(ドロップダウンリスト)を作ってくれるJSライブラリです。

使い方

npmでインストール

npm i tom-select

CDNで読み込み

GitHubからファイルのダウンロード

以下のライセンスを守って【Tom Select】を使います。

実装例の説明

HTML

<!-- Tom Select使用|CSSアレンジ -->
      <div class="select__wrap select__wrap--css">
        <h2 class="select__title">CSSアレンジ(Tom Select使用)</h2>
        <select id="select__css" class="select" name="select_test_css" autocomplete="off">
          <!-- ↓ valueの値を空にすることで、placeholderのように扱える|Tom Select -->
          <option value="">選択して下さい</option>
          <option value="ここに">ここに</option>
          <option value="CSSが">CSSが</option>
          <option value="効く!">効く!</option>
          <option value="そう、">そう、</option>
          <option value="Tom Selectならね。">Tom Selectならね。</option>
        </select>
      </div>

<!-- Tom Select使用|グループ分け -->
      <div class="select__wrap">
        <h2 class="select__title">グループ分け・タイトル・画像(Tom Select使用)</h2>
        <p>【例】島根県について知っていることを選択してください。(3つまで)</p>
        <select id="select__group" class="select" name="select_test_charas" autocomplete="off">
          <option value="">選択して下さい</option>
        </select>
      </div>

上記がTomSelectを使用しているHTMLの記述です。
一般的なselect要素の記述方法と変わりないことが確認できると思います。

15行目のグループ分けに関しては、JavaScriptにて擬似的なoption要素を作成しているので、HTML上には記述していません。

SCSS

/* リセットCSS ------------------------------- */
*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

body {
  background: #fff;
}

/* アクセシビリティ用 ------------------------------- */
/* マウスクリック操作の場合は ouline を消し、キーボード操作の場合は outline を表示する場合 */
:focus:not(:focus-visible) {
  outline: 0;
}

/* アウトライン表示 */
:focus-visible,
.ts-wrapper.focus {
  outline: 2px solid red;
  outline-offset: 0;
}

最低限のリセットCSSと、フォーカス用のCSSです。

22行目の[ .ts-wrapper.focus ] にて、TomSelectが生成した要素にフォーカスされた時のCSSを記述しています。この記述によって、マウスクリック・キーボード操作ともにアウトラインが表示されるようにしています。

/* -------------------------------------------------------------------- */
/*
/* Tom Select用CSS
/* -------------------------------------------------------------------- */

// セレクトボックスCSS
.ts-control {
  display: flex; // select欄、文字中央
  align-items: center;
  padding-left: 1em;
}

// ドロップダウンCSS
.ts-dropdown {
  margin-top: 0.2rem;

  // 画像配置時のテキスト位置
  .option {
    display: flex;
    align-items: center;
  }
}

.ts-control {

  // 画像配置時のテキスト位置
  .item {
    display: flex;
    align-items: center;
  }
}

// 文字関連
.ts-control,
.ts-control input,
.ts-dropdown {
  font-smoothing: inherit;
  color: #333;
  font-family: inherit;
  font-size: 16px;
  line-height: 1.5;
}

// グループのタイトル
.ts-dropdown .optgroup-header {
  font-size: 20px;
  font-weight: bold;
  background-color: cornsilk;
  padding-top: 30px;
  padding-bottom: 10px;
  padding-left: 15px;
}

TomSelect用のCSSです。
TomSelectが生成した要素にCSSを当てる必要があります。

詳しくは、ブラウザの【検証(開発者ツール)】を使って、生成された要素を確認してみてください。

JavaScript

(function () {

// CSSアレンジ用のJS
  new TomSelect('#select__css');

// グループ分け用のJS
  new TomSelect('#select__group', {
    maxItems: 3, // 最大3つまで選択できる
    options: [ // option要素のデータ
      { class: 'area', src: 'https://picsum.photos/500/500', value: '足立美術館(安来市古川町)' },
      { class: 'area', src: 'https://picsum.photos/500/500', value: '出雲大社(出雲市大社町)' },
      { class: 'area', src: 'https://picsum.photos/500/500', value: '松江城(松江市殿町)' },
      { class: 'area', src: 'https://picsum.photos/500/500', value: '海洋館アクアス(浜田市久代町)' },
      { class: 'area', src: 'https://picsum.photos/500/500', value: '由志園(松江市八束町)' },
      { class: 'goods', src: 'https://picsum.photos/500/500', value: '宍道湖の殻つきしじみ' },
      { class: 'goods', src: 'https://picsum.photos/500/500', value: 'しじみ佃煮' },
      { class: 'goods', src: 'https://picsum.photos/500/500', value: '出雲そば' },
      { class: 'goods', src: 'https://picsum.photos/500/500', value: 'のどぐろ加工品' },
      { class: 'goods', src: 'https://picsum.photos/500/500', value: 'あご野焼' }
    ],
    optgroups: [ // グループのタイトル
      { value: 'area', label: '島根県の観光地' },
      { value: 'goods', label: '島根県の特産品' }
    ],
    optgroupField: 'class', // 項目をグループ化するデータ名
    labelField: 'value', // labelとして表示するデータ名
    searchField: ['value'], // オプションをフィルタリングする際のデータ名
    render: {
      option: function (data, escape) { // ドロップダウン内リストを生成
        return '<div>' + '<img src="' + escape(data.src) + '">' + escape(data.value) + '</div>';
      },
      item: function (data, escape) { // 選択された項目を生成
        return '<div>' + '<img src="' + escape(data.src) + '">' + escape(data.value) + '</div>';
      },
      optgroup_header: function (data, escape) { // グループのタイトルを生成
        return '<div class="optgroup-header">' + escape(data.label) + '</div>';
      },
    }
  });

}());

TomSelectの基本的な使い方は、JavaScriptに以下を記述するだけで使うことが出来ます。

new TomSelect('#select要素のID名');

この記述をするとWebページにTomSelect用のHTMLが生成されて、そこにCSSを記述することで、あたかもoption要素にCSSが当たっているかのような見た目になります。インチキ…

7行目からは、グループ分け・グループタイトル・画像・テキストの記述をしています。
optionとなる要素に画像を設置したかったら、
30行・33行目のところでimg要素を出力するように記述すれば良いです。

詳しい使い方は公式をご覧ください。

まとめ

Tom Select…もっと早く知っておきたかったです(泣
この記事がお役に立てれば幸いです。

参考リンク

シェアしてもいいかも…と、思ったら

記事 一覧へ

コメントを書いてみる

CAPTCHA