選択肢をゆっくり表示するセレクトボックスを作る方法
選択肢をゆっくり表示するセレクトボックスを作る方法を紹介します。ボタンをクリックすると、配送方法の選択肢が上からふんわりと現れ、選択すると一覧がゆっくり閉じるカスタムセレクトボックスです。通常のselect要素では開いた選択肢へ自由なアニメーションを設定できないため、HTML・CSS・JavaScriptを使って独自の選択UIを実装します。
サンプルでは「宅配便」「メール便」「店頭受取」の3項目を用意し、選択した内容をボタン部分へ反映します。お問い合わせ画面、ECサイトの注文画面、会員サイトの設定画面、管理画面の絞り込みフォームなど、選択肢を急に表示せず、落ち着いた動きで案内したい場面に利用できます。
選択肢が開閉する時間、移動距離、背景色、枠線、角丸、表示項目はコードから変更できます。右側の矢印には画像を使用しており、一覧を開くと上下方向が切り替わります。画面幅に合わせて横幅が縮小するため、スマートフォン・タブレット・PCでも利用しやすい構成です。
コードについて
本記事のコードはサンプルコードです。ご利用前に必ず動作確認を行ってください。
免責事項
本コードの利用により発生した損害について、当サイトは一切の責任を負いません。
デモ
配送方法を選択
セレクトボックスをクリックすると、選択肢がゆっくり表示されます。
選択中:未選択
「選択してください」をクリックすると、配送方法の選択肢がゆっくり表示されます。項目を選択すると、選択した内容がボタンと結果欄へ反映されます。
コードをコピーして使おう!
<!DOCTYPE html>
<html lang="ja">
<head>
<!-- 文字コードをUTF-8へ設定 -->
<meta charset="UTF-8">
<!-- スマートフォン・タブレット表示へ対応 -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- ブラウザのタブへ表示するタイトル -->
<title>選択肢をゆっくり表示するセレクトボックス</title>
<!-- CSSファイルを読み込み -->
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- カスタムセレクトボックス全体 -->
<div class="slow-options-selectbox">
<!-- セレクトボックスエリアのタイトル -->
<div class="slow-options-selectbox_title">
配送方法を選択
</div>
<!-- 動作を案内する説明文 -->
<p class="slow-options-selectbox_text">
セレクトボックスをクリックすると、選択肢がゆっくり表示されます。
</p>
<!-- セレクトボックスのラベル -->
<div
class="slow-options-selectbox_label"
id="slow-options-selectbox-label">
配送方法
</div>
<!-- ボタン・選択肢・送信用データをまとめる要素 -->
<div class="slow-options-selectbox_control">
<!-- 選択肢一覧を開閉するボタン -->
<button
class="slow-options-selectbox_button"
id="slow-options-selectbox-button"
type="button"
aria-labelledby="slow-options-selectbox-label slow-options-selectbox-value"
aria-haspopup="listbox"
aria-expanded="false"
aria-controls="slow-options-selectbox-options">
<!-- 現在の選択内容 -->
<span id="slow-options-selectbox-value">
選択してください
</span>
<!--
右側の下向き矢印画像
width="18" height="12"
数値を大きくすると矢印画像が大きくなる
-->
<img
class="slow-options-selectbox_arrow"
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='18' height='12' viewBox='0 0 18 12'%3E%3Cpath d='M1 1.5L9 10.5L17 1.5Z' fill='%230f172a'/%3E%3C/svg%3E"
alt=""
aria-hidden="true">
</button>
<!-- ゆっくり表示する選択肢一覧 -->
<ul
class="slow-options-selectbox_options"
id="slow-options-selectbox-options"
role="listbox"
aria-labelledby="slow-options-selectbox-label">
<!-- 宅配便 -->
<li role="none">
<button
class="slow-options-selectbox_option"
type="button"
role="option"
data-value="宅配便"
aria-selected="false">
宅配便
</button>
</li>
<!-- メール便 -->
<li role="none">
<button
class="slow-options-selectbox_option"
type="button"
role="option"
data-value="メール便"
aria-selected="false">
メール便
</button>
</li>
<!-- 店頭受取 -->
<li role="none">
<button
class="slow-options-selectbox_option"
type="button"
role="option"
data-value="店頭受取"
aria-selected="false">
店頭受取
</button>
</li>
</ul>
<!-- フォーム送信時に選択内容を渡す隠し入力欄 -->
<input
id="slow-options-selectbox-input"
type="hidden"
name="delivery"
value="">
</div>
<!-- 現在の選択内容を表示する結果欄 -->
<p
class="slow-options-selectbox_result"
id="slow-options-selectbox-result"
aria-live="polite">
選択中:未選択
</p>
</div>
<!-- JavaScriptファイルを読み込み -->
<script src="script.js"></script>
</body>
</html>
/* ページ全体 */
body{
margin:0; /* ブラウザ標準の外側余白を削除 */
padding:40px 20px; /* 上下40px・左右20px。値を大きくすると画面端との間隔が広がる */
background:#ffffff; /* ページ全体の背景色 */
color:#111827; /* ページ全体の基本文字色 */
font-family:sans-serif; /* ページ全体で使用するフォント */
}
/* カスタムセレクトボックス全体 */
.slow-options-selectbox{
width:100%; /* 画面幅に合わせて横幅を縮小 */
max-width:720px; /* 最大横幅。900pxにすると広く、500pxにするとコンパクトになる */
margin:40px auto; /* 上下40pxの余白を付けて左右中央へ配置 */
padding:36px; /* 内側余白。48pxにすると広く、24pxにすると狭くなる */
border:1px solid #dbe5f1; /* 外枠の太さ・種類・色 */
border-radius:20px; /* 全体の角丸。30pxにすると丸く、0にすると四角くなる */
background:#f8fafc; /* 全体の背景色 */
box-sizing:border-box; /* paddingとborderを横幅へ含める */
}
/* タイトル */
.slow-options-selectbox_title{
margin:0 0 14px; /* 下側14pxの余白。値を大きくすると説明文との間隔が広がる */
color:#111827; /* タイトルの文字色 */
font-size:30px; /* タイトルの文字サイズ。36pxにすると大きくなる */
font-weight:700; /* タイトルを太字にする */
line-height:1.5; /* タイトルの行間 */
text-align:center; /* タイトルを中央揃えにする */
}
/* 説明文 */
.slow-options-selectbox_text{
margin:0 0 32px; /* 下側32pxの余白。値を大きくするとラベルとの間隔が広がる */
color:#64748b; /* 説明文の文字色 */
font-size:16px; /* 説明文の文字サイズ。18pxにすると大きくなる */
line-height:1.8; /* 説明文の行間。値を大きくすると行間が広がる */
text-align:center; /* 説明文を中央揃えにする */
}
/* ラベル */
.slow-options-selectbox_label{
margin-bottom:10px; /* 下側10pxの余白。値を大きくするとボタンとの間隔が広がる */
color:#111827; /* ラベルの文字色 */
font-size:17px; /* ラベルの文字サイズ。20pxにすると大きくなる */
font-weight:700; /* ラベルを太字にする */
line-height:1.5; /* ラベルの行間 */
}
/* ボタンと選択肢一覧をまとめる要素 */
.slow-options-selectbox_control{
position:relative; /* 選択肢一覧をこの要素を基準に配置 */
width:100%; /* 親要素の横幅いっぱいに表示 */
}
/* 選択肢一覧を開閉するボタン */
.slow-options-selectbox_button{
display:flex; /* 選択内容と矢印を横並びにする */
align-items:center; /* 縦方向の中央へ揃える */
justify-content:space-between; /* 選択内容と矢印を左右へ配置 */
gap:20px; /* 文字と矢印の間隔。値を大きくすると間隔が広がる */
width:100%; /* 横幅いっぱいに表示 */
min-height:58px; /* ボタンの最低高さ。70pxにすると高く、50pxにすると低くなる */
padding:14px 18px; /* 上下14px・左右18px。値を大きくするとボタンが大きくなる */
border:2px solid #cbd5e1; /* ボタンの枠線 */
border-radius:14px; /* ボタンの角丸。24pxにすると丸みが強くなる */
background:#ffffff; /* ボタンの背景色 */
color:#111827; /* ボタンの文字色 */
font-size:16px; /* ボタンの文字サイズ。18pxにすると大きくなる */
line-height:1.5; /* ボタン文字の行間 */
text-align:left; /* ボタン文字を左揃えにする */
cursor:pointer; /* マウスカーソルを指型へ変更 */
box-sizing:border-box; /* paddingとborderを横幅へ含める */
}
/* ボタンへマウスを重ねた状態 */
.slow-options-selectbox_button:hover{
border-color:#94a3b8; /* マウスを重ねた時の枠線色 */
}
/* ボタンへフォーカスした状態 */
.slow-options-selectbox_button:focus{
border-color:#2563eb; /* フォーカス時の枠線色 */
outline:3px solid rgba(37,99,235,0.18); /* 外側の強調表示。3pxを大きくすると太くなる */
outline-offset:2px; /* ボタンと外枠の間隔。値を大きくすると外側へ離れる */
}
/* 右側の矢印画像 */
.slow-options-selectbox_arrow{
flex-shrink:0; /* 横幅が縮まないようにする */
display:block; /* 画像下の不要な隙間を防ぐ */
width:18px; /* 矢印の横幅。24pxにすると大きくなる */
height:12px; /* 矢印の高さ。16pxにすると大きくなる */
object-fit:contain; /* 矢印画像の比率を保つ */
transition:transform 0.4s ease; /* 0.4秒で矢印を回転。0.8sにするとゆっくり、0.2sにすると速くなる */
}
/* 選択肢一覧を開いた時の矢印 */
.slow-options-selectbox_button[aria-expanded="true"]
.slow-options-selectbox_arrow{
transform:rotate(180deg); /* 矢印を180度回転して上向きにする */
}
/* 選択肢一覧 */
.slow-options-selectbox_options{
position:absolute; /* ボタンの下へ重ねて表示 */
top:calc(100% + 10px); /* ボタン下から10px離して表示。20pxにすると間隔が広がる */
left:0; /* 左端を揃える */
z-index:10; /* 周囲の要素より手前へ表示 */
width:100%; /* ボタンと同じ横幅にする */
margin:0; /* 外側余白を削除 */
padding:8px; /* 選択肢一覧の内側余白。16pxにすると広くなる */
border:1px solid #cbd5e1; /* 選択肢一覧の枠線 */
border-radius:14px; /* 選択肢一覧の角丸。24pxにすると丸みが強くなる */
background:#ffffff; /* 選択肢一覧の背景色 */
box-shadow:0 18px 38px rgba(15,23,42,0.16); /* 一覧の影。数値を大きくすると影が広がる */
list-style:none; /* リストの黒丸を非表示 */
box-sizing:border-box; /* paddingとborderを横幅へ含める */
opacity:0; /* 閉じている時は透明 */
visibility:hidden; /* 閉じている時は非表示 */
transform:translateY(-12px); /* 閉じている時は12px上へ配置。24pxにすると移動距離が大きくなる */
pointer-events:none; /* 閉じている時は操作を無効化 */
transition:
opacity 0.6s ease,
transform 0.6s ease,
visibility 0.6s;
/*
0.6秒で選択肢一覧をゆっくり表示する。
1sにするとさらにゆっくり表示され、
0.3sにすると素早く表示される。
3か所の0.6sを同じ値へ変更する。
*/
}
/* 選択肢一覧を開いた状態 */
.slow-options-selectbox_options.is-open{
opacity:1; /* 一覧を不透明にして表示 */
visibility:visible; /* 一覧を表示 */
transform:translateY(0); /* 元の位置までゆっくり移動 */
pointer-events:auto; /* 一覧を操作可能にする */
}
/* 各選択肢 */
.slow-options-selectbox_option{
width:100%; /* 一覧の横幅いっぱいに表示 */
padding:13px 14px; /* 上下13px・左右14px。値を大きくすると選択肢が高くなる */
border:0; /* ボタン標準の枠線を非表示 */
border-radius:9px; /* 選択肢の角丸。値を大きくすると丸みが強くなる */
background:transparent; /* 通常時の背景を透明にする */
color:#111827; /* 選択肢の文字色 */
font-size:16px; /* 選択肢の文字サイズ。18pxにすると大きくなる */
line-height:1.5; /* 選択肢の行間 */
text-align:left; /* 選択肢を左揃えにする */
cursor:pointer; /* マウスカーソルを指型へ変更 */
box-sizing:border-box; /* paddingを横幅へ含める */
}
/* 選択肢へマウスを重ねた状態・フォーカスした状態 */
.slow-options-selectbox_option:hover,
.slow-options-selectbox_option:focus{
background:#eaf2ff; /* 強調時の背景色 */
color:#1d4ed8; /* 強調時の文字色 */
outline:none; /* ブラウザ標準の外枠を非表示 */
}
/* 選択済みの項目 */
.slow-options-selectbox_option.is-selected{
background:#2563eb; /* 選択済み項目の背景色 */
color:#ffffff; /* 選択済み項目の文字色 */
}
/* 選択結果欄 */
.slow-options-selectbox_result{
margin:28px 0 0; /* 上側28pxの余白。値を大きくすると一覧との間隔が広がる */
padding:15px 18px; /* 上下15px・左右18px。値を大きくすると結果欄が大きくなる */
border:1px solid #bfdbfe; /* 結果欄の枠線 */
border-radius:12px; /* 結果欄の角丸 */
background:#eff6ff; /* 結果欄の背景色 */
color:#1d4ed8; /* 結果欄の文字色 */
font-size:16px; /* 結果欄の文字サイズ */
font-weight:700; /* 結果欄の文字を太字にする */
line-height:1.6; /* 結果欄の行間 */
}
/* 画面幅640px以下 */
@media screen and (max-width:640px){
/* スマートフォン表示時のページ全体 */
body{
padding:24px 12px; /* 上下24px・左右12pxへ縮小 */
}
/* スマートフォン表示時の全体 */
.slow-options-selectbox{
margin:24px auto; /* 上下余白を24pxへ縮小 */
padding:24px 18px; /* 上下24px・左右18pxへ縮小 */
}
/* スマートフォン表示時のタイトル */
.slow-options-selectbox_title{
font-size:24px; /* タイトルを24pxへ縮小 */
}
/* スマートフォン表示時のボタン */
.slow-options-selectbox_button{
min-height:54px; /* ボタンの最低高さを54pxへ縮小 */
padding:13px 15px; /* 上下13px・左右15pxへ縮小 */
}
}
// 選択肢一覧を開閉するボタンを取得
const slowOptionsSelectboxButton=document.getElementById(
"slow-options-selectbox-button"
);
// 選択肢一覧を取得
const slowOptionsSelectboxOptions=document.getElementById(
"slow-options-selectbox-options"
);
// 現在の選択内容を表示する要素を取得
const slowOptionsSelectboxValue=document.getElementById(
"slow-options-selectbox-value"
);
// フォーム送信用の隠し入力欄を取得
const slowOptionsSelectboxInput=document.getElementById(
"slow-options-selectbox-input"
);
// 選択結果を表示する要素を取得
const slowOptionsSelectboxResult=document.getElementById(
"slow-options-selectbox-result"
);
// すべての選択肢ボタンを取得
const slowOptionsSelectboxOptionButtons=
slowOptionsSelectboxOptions.querySelectorAll(
".slow-options-selectbox_option"
);
// 選択肢一覧を開く処理
function openSlowOptionsSelectbox(){
// CSSの表示用クラスを追加
slowOptionsSelectboxOptions.classList.add("is-open");
// 一覧が開いていることを設定
slowOptionsSelectboxButton.setAttribute(
"aria-expanded",
"true"
);
}
// 選択肢一覧を閉じる処理
function closeSlowOptionsSelectbox(){
// CSSの表示用クラスを削除
slowOptionsSelectboxOptions.classList.remove("is-open");
// 一覧が閉じていることを設定
slowOptionsSelectboxButton.setAttribute(
"aria-expanded",
"false"
);
}
// 開閉ボタンをクリックした時
slowOptionsSelectboxButton.addEventListener("click",function(){
// 現在の開閉状態を確認
const isOpen=
slowOptionsSelectboxButton.getAttribute("aria-expanded")==="true";
// 開いている場合
if(isOpen){
// 選択肢一覧を閉じる
closeSlowOptionsSelectbox();
}else{
// 選択肢一覧を開く
openSlowOptionsSelectbox();
}
});
// 各選択肢へクリック処理を設定
slowOptionsSelectboxOptionButtons.forEach(function(option){
// 選択肢をクリックした時
option.addEventListener("click",function(){
// 選択した値を取得
const selectedValue=option.dataset.value;
// ボタンへ選択した値を表示
slowOptionsSelectboxValue.textContent=selectedValue;
// フォーム送信用の値を更新
slowOptionsSelectboxInput.value=selectedValue;
// 結果欄へ選択した値を表示
slowOptionsSelectboxResult.textContent=
"選択中:"+selectedValue;
// すべての選択肢の状態を更新
slowOptionsSelectboxOptionButtons.forEach(function(item){
// 現在処理中の項目が選択項目か確認
const isSelected=item===option;
// 選択済みデザインを切り替え
item.classList.toggle(
"is-selected",
isSelected
);
// アクセシビリティ用の選択状態を更新
item.setAttribute(
"aria-selected",
String(isSelected)
);
});
// 選択肢一覧を閉じる
closeSlowOptionsSelectbox();
// 開閉ボタンへフォーカスを戻す
slowOptionsSelectboxButton.focus();
});
});
// ページ内をクリックした時
document.addEventListener("click",function(event){
// カスタムセレクトボックス全体を取得
const control=slowOptionsSelectboxButton.closest(
".slow-options-selectbox_control"
);
// カスタムセレクトボックスの外側をクリックした場合
if(!control.contains(event.target)){
// 選択肢一覧を閉じる
closeSlowOptionsSelectbox();
}
});
// キーボードを押した時
document.addEventListener("keydown",function(event){
// ESCキーを押した場合
if(event.key==="Escape"){
// 選択肢一覧を閉じる
closeSlowOptionsSelectbox();
// 開閉ボタンへフォーカスを戻す
slowOptionsSelectboxButton.focus();
}
});
コードをコピーする場合
使用するコードのタブを選び、「このタブをコピー」をクリックすると、現在表示中のコードをコピーできます。
サンプル一式を取得する場合
HTML・CSSなどすべてのファイルが必要な場合は、「サンプル一式をダウンロード」をクリックしてください。
ファイル構成と設置方法
このサンプルはHTML・CSS・JavaScriptの3ファイルで構成されています。JavaScriptでセレクトボックスをクリックした際に選択肢一覧をふんわり表示し、CSSでアニメーションやデザインを設定しています。HTMLは画面構成のみを担当しているため、それぞれの役割が分かれており、初心者でも編集しやすい構成です。
sample/
├── index.html
├── style.css
└── script.js
各ファイルの役割
index.htmlはセレクトボックスと画面全体のレイアウトを記述しています。表示する項目や説明文を変更したい場合はこのファイルを編集します。
style.cssはカードデザインやセレクトボックスの見た目、選択肢一覧のアニメーションを管理しています。色・サイズ・余白・角丸・影・アニメーション速度などを変更できます。
script.jsはセレクトボックスを開閉する処理や、選択した内容を表示する処理を担当しています。動作を変更したい場合はこのファイルを編集します。
設置方法・使い方
sampleフォルダをそのまま保存し、sample/index.htmlをブラウザで開くだけで利用できます。追加のライブラリやサーバー設定は不要で、HTML・CSS・JavaScriptのみで動作します。
カスタマイズできる内容
index.htmlでは選択肢の追加・削除・変更ができます。
style.cssでは背景色・文字色・枠線・角丸・余白・横幅・影・選択肢一覧の表示デザインを変更できます。
script.jsでは表示・非表示のタイミングや開閉処理を変更できます。
数値調整
style.css
transition: opacity 0.35s ease;
→ 0.35は選択肢一覧が表示・非表示になる時間です。0.7へ変更すると約0.7秒かけてゆっくり表示され、0.15へ変更すると素早く表示されます。
style.css
transform: translateY(10px);
→ 10pxは表示開始位置です。20pxへ変更すると少し下から表示され、5pxへ変更すると移動量が小さくなります。
style.css
border-radius:16px;
→ 16pxは角丸の大きさです。24pxへ変更すると丸みが強くなり、8pxへ変更すると角が少し四角くなります。
style.css
padding:16px 18px;
→ 16px・18pxはセレクトボックス内の余白です。数値を大きくすると高さや余白が広くなります。
レスポンシブ対応
このサンプルはレスポンシブ対応しています。style.cssでwidth:100%、max-width、paddingを利用しており、画面幅に合わせてレイアウトが自動調整されます。PC・タブレット・スマートフォンでも見やすいサイズで利用できます。
コメント