JavaScript
 Computer >> コンピューター >  >> プログラミング >> JavaScript

CSSとJavaScriptでカスタムセレクトボックスを作成する方法【実装例つき】

HTML標準の<select>要素はブラウザごとに見た目が異なり、デザインの自由度が低いという課題があります。そこで本記事では、CSSとJavaScriptを組み合わせて、見た目を自由にカスタマイズできるオリジナルのセレクトボックス(ドロップダウンメニュー)を作成する方法を解説します。

実装のポイント

カスタムセレクトボックスを実装する際の基本的な考え方は以下の通りです。

  • 元となる<select>要素はCSSで非表示にし、データ保持用として利用します
  • 選択状態を表示する要素(.select-selected)と、選択肢一覧を表示する要素(.select-items)をJavaScriptで動的に生成します
  • 矢印アイコンはCSSの擬似要素(:after)とborderプロパティを使って描画します

コード例

以下がカスタムセレクトボックスの完全なサンプルコードです。

<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>
    .customSelect {
        position: relative;
        font-family: Arial, Helvetica, sans-serif;
    }
    .customSelect select {
        display: none;
    }
    .select-selected {
        background-color: rgb(78, 11, 122);
    }
    .select-selected:after {
        position: absolute;
        content: "";
        top: 14px;
        right: 10px;
        width: 0;
        height: 0;
        border: 6px solid transparent;
        border-color: #fff transparent transparent transparent;
    }
    .select-selected.select-arrow-active:after {
        border-color: transparent transparent #fff transparent;
        top: 7px;
    }
    .select-items div, .select-selected {
        color: #ffffff;
        padding: 8px 16px;
        border: 1px solid transparent;
        cursor: pointer;
        user-select: none;
    }
    .select-items {
        position: absolute;
        background-color: rgb(138, 29, 148);
        top: 100%;
        left: 0;
        right: 0;
        z-index: 99;
    }
    .select-hide {
        display: none;
    }
    .select-items div:hover, .sameSelected {
        background-color: rgba(0, 0, 0, 0.1);
    }
</style>
</head>
<body>
<h1>Custom Select Example</h1>
<div class="customSelect" style="width:200px;">
<select>
<option value="0">Select Animal:</option>
<option value="Giraffe">Giraffe</option>
<option value="Lion">Lion</option>
<option value="Cow">Cow</option>
<option value="Dog">Dog</option>
<option value="Tiger">Tiger</option>
</select>
</div>
<script>
    var customSelectEle, i, j, selElmnt, divEle, divEleSelected, c;
    customSelectEle = document.querySelector(".customSelect");
    selElmnt = customSelectEle.getElementsByTagName("select")[0];
    divEle = document.createElement("DIV");
    divEle.setAttribute("class", "select-selected");
    divEle.innerHTML = selElmnt.options[selElmnt.selectedIndex].innerHTML;
    customSelectEle.appendChild(divEle);
    divEleSelected = document.createElement("DIV");
    divEleSelected.setAttribute("class", "select-items select-hide");
    Array.from(selElmnt).forEach((item, index) => {
        c = document.createElement("DIV");
        c.innerHTML = selElmnt.options[index].innerHTML;
        c.addEventListener("click", function(e) {
            var y, i, k, selEleParent, selEleSibling;
            selEleParent = this.parentNode.parentNode.getElementsByTagName( "select" )[0];
            selEleSibling = this.parentNode.previousSibling;
            for (i = 0; i < selEleParent.length; i++) {
                if (selEleParent.options[i].innerHTML == this.innerHTML) {
                    selEleParent.selectedIndex = i;
                    selEleSibling.innerHTML = this.innerHTML;
                    y = this.parentNode.getElementsByClassName("sameSelected");
                    for (k = 0; k < y.length; k++) {
                        y[k].removeAttribute("class");
                    }
                    this.setAttribute("class", "sameSelected");
                    break;
                }
            }
            selEleSibling.click();
        });
        divEleSelected.appendChild(c);
    });
    customSelectEle.appendChild(divEleSelected);
    divEle.addEventListener("click", function(e) {
        e.stopPropagation();
        closeSelect(this);
        this.nextSibling.classList.toggle("select-hide");
        this.classList.toggle("select-arrow-active");
    });
    function closeSelect(elmnt) {
        var customSelectEle,
        y,
        i,
        arrNo = [];
        customSelectEle = document.getElementsByClassName("select-items");
        y = document.getElementsByClassName("select-selected");
        for (i = 0; i < y.length; i++) {
            if (elmnt == y[i]) {
                arrNo.push(i);
            }
            else {
                y[i].classList.remove("select-arrow-active");
            }
        }
        for (i = 0; i < customSelectEle.length; i++) {
            if (arrNo.indexOf(i)) {
                customSelectEle[i].classList.add("select-hide");
            }
        }
    }
    document.addEventListener("click", closeSelect);
</script>
</body>
</html>

コードの解説

このコードの動作を簡単に整理すると、次のような流れになります。

1. 表示用要素の生成

まず、元の<select>要素から現在選択されているオプションのテキストを取得し、.select-selectedクラスを持つDIV要素として画面に表示します。続いて、全てのオプションに対応する選択肢要素(DIV)を生成し、.select-items select-hideクラスを付けたコンテナに格納します。初期状態ではselect-hideにより非表示になっています。

2. 選択処理

各選択肢がクリックされると、対応する元の<select>selectedIndexを更新し、表示用要素のテキストも書き換えます。同時に、選択中の項目に.sameSelectedクラスを付与してハイライト表示します。

3. 開閉の制御

表示用要素のクリックでclassList.toggle()によりメニューの表示・非表示を切り替え、矢印アイコンの向きも.select-arrow-activeクラスで反転させます。また、closeSelect()関数をdocumentのクリックイベントに登録することで、メニュー外をクリックした際にも自動的に閉じるようになっています。

出力結果

上記のコードを実行すると、次のようなカスタムセレクトボックスが表示されます。

CSSとJavaScriptでカスタムセレクトボックスを作成する方法【実装例つき】

セレクトボックスをクリックすると、選択肢一覧がドロップダウン形式で展開されます。

CSSとJavaScriptでカスタムセレクトボックスを作成する方法【実装例つき】

まとめ

CSSとJavaScriptを組み合わせれば、ブラウザ標準のセレクトボックスの制約を受けずに、自由なデザインのドロップダウンメニューを実装できます。色や余白、フォントなどをCSSで調整すれば、サイトのデザインに合わせたUIを簡単に作れるので、ぜひ参考にしてみてください。

  1. JavaScriptとCSSでドラッグ可能なHTML要素を作成する方法

    JavaScriptとCSSを組み合わせることで、マウスで掴んで自由に移動できる「ドラッグ可能なHTML要素」を簡単に実装できます。本記事では、実際に動作するサンプルコードと、その内部処理の仕組みをわかりやすく解説します。 ドラッグ可能なDIV要素のサンプルコード 以下のコードでは、position: absoluteで配置したDIV要素に対して、マウスイベント(mousedown・mousemove・mouseup)を利用してドラッグ機能を実装しています。 <!DOCTYPE html> <html> <style> body {

  2. CSSとJavaScriptでアコーディオン(開閉パネル)を作成する方法をわかりやすく解説

    CSSとJavaScriptを組み合わせることで、クリックすると内容が開閉する「アコーディオン(折りたたみパネル)」を簡単に実装できます。本記事では、実際に動作するサンプルコードをもとに、その作成手順と仕組みを詳しく解説します。 アコーディオンの実装例 以下は、HTML・CSS・JavaScriptを使ってアコーディオンを実装した完全なサンプルコードです。 <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width, ini