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…もっと早く知っておきたかったです(泣
この記事がお役に立てれば幸いです。