立体的な選択肢が開くセレクトボックスを作る方法
立体的な選択肢が開くセレクトボックスを作る方法を紹介します。このサンプルでは、HTML・CSS・JavaScriptを使用し、フラットな見出し部分をクリックすると、その下に複数の選択肢が手前へ浮き出すような立体デザインで表示されます。通常のセレクトボックスとは異なり、開いた選択肢それぞれに厚みと影を付けることで、押せる項目であることが視覚的に分かりやすいデザインになっています。
「商品について」「サービスについて」「料金について」「その他」の4つの選択肢を表示し、クリックした項目を現在の選択内容として見出し部分へ反映します。選択された項目は青色へ切り替わり、その後に選択肢一覧が閉じます。見出し自体は立体化せず、開いた選択肢だけを立体的に見せるため、通常のフォームに取り入れながら選択部分だけを強調したい場合にも利用できます。
HTMLでは見出しや選択肢の文章を変更できます。CSSでは選択肢の間隔、背景色、枠線、角丸、影の大きさ、手前へ浮き出す距離、開閉アニメーションなどを調整できます。JavaScriptでは見出しの開閉、選択状態の切り替え、選択した文字の反映を行います。画面幅が狭い場合には余白や選択肢同士の間隔を調整するレスポンシブ対応も含まれているため、スマートフォン・タブレット・PCで利用できます。
コードについて
本記事のコードはサンプルコードです。ご利用前に必ず動作確認を行ってください。
免責事項
本コードの利用により発生した損害について、当サイトは一切の責任を負いません。
デモ
立体的な選択肢が開くセレクトボックス
見出しをクリックすると、選択肢が手前へ浮き出すように表示されます。
お問い合わせ内容
商品について
商品について
サービスについて
料金について
その他
見出しはフラットなまま表示し、開いた選択肢だけを立体的にせり出して表示します。
コードをコピーして使おう!
html
css
js
このタブをコピー
サンプル一式をダウンロード
<!DOCTYPE html>
<html lang="ja">
<head>
<!-- 文字コード -->
<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="three-dimensional-select-box_wrap">
<!-- タイトル -->
<div class="three-dimensional-select-box_title">
立体的な選択肢が開くセレクトボックス
</div>
<!-- 説明文 -->
<p class="three-dimensional-select-box_text">
見出しをクリックすると、選択肢が手前へ浮き出すように表示されます。
</p>
<!-- 選択エリア -->
<div class="three-dimensional-select-box_field">
<!-- 項目名 -->
<div class="three-dimensional-select-box_label">
お問い合わせ内容
</div>
<!-- 選択中の内容を表示する見出し -->
<button
class="three-dimensional-select-box_trigger"
type="button"
aria-expanded="false">
<span class="three-dimensional-select-box_value">
商品について
</span>
<!-- 開閉アイコン -->
<span
class="three-dimensional-select-box_arrow"
aria-hidden="true">
</span>
</button>
<!-- 選択肢一覧 -->
<ul class="three-dimensional-select-box_options">
<li class="three-dimensional-select-box_option">
<button
class="three-dimensional-select-box_option-button is-selected"
type="button"
data-value="商品について">
商品について
</button>
</li>
<li class="three-dimensional-select-box_option">
<button
class="three-dimensional-select-box_option-button"
type="button"
data-value="サービスについて">
サービスについて
</button>
</li>
<li class="three-dimensional-select-box_option">
<button
class="three-dimensional-select-box_option-button"
type="button"
data-value="料金について">
料金について
</button>
</li>
<li class="three-dimensional-select-box_option">
<button
class="three-dimensional-select-box_option-button"
type="button"
data-value="その他">
その他
</button>
</li>
</ul>
</div>
</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; /* 使用するフォント */
}
/* セレクトボックス全体 */
.three-dimensional-select-box_wrap{
width:100%; /* 画面幅に合わせて縮小 */
max-width:700px; /* 最大横幅 */
margin:40px auto; /* 上下40pxの余白を付けて左右中央へ配置 */
padding:36px 32px 42px; /* 上36px・左右32px・下42pxの内側余白 */
border:1px solid #dbe3ef; /* 外枠 */
border-radius:20px; /* 全体の角丸 */
background:#f8fafc; /* 全体の背景色 */
color:#111827; /* 基本文字色 */
box-sizing:border-box; /* paddingとborderを横幅へ含める */
}
/* セレクトボックス内の全要素 */
.three-dimensional-select-box_wrap *{
box-sizing:border-box; /* paddingとborderを要素サイズへ含める */
}
/* タイトル */
.three-dimensional-select-box_title{
margin:0 0 12px; /* 下側12pxの余白 */
font-size:22px; /* タイトルの文字サイズ */
font-weight:700; /* タイトルを太字にする */
line-height:1.5; /* タイトルの行間 */
text-align:center; /* 中央揃え */
}
/* 説明文 */
.three-dimensional-select-box_text{
margin:0 0 30px; /* 下側30pxの余白 */
color:#4b5563; /* 説明文の文字色 */
font-size:16px; /* 説明文の文字サイズ */
line-height:1.8; /* 説明文の行間 */
text-align:center; /* 中央揃え */
}
/* 選択エリア */
.three-dimensional-select-box_field{
position:relative; /* 選択肢を配置する基準 */
width:100%; /* 横幅いっぱいに表示 */
max-width:460px; /* 選択エリアの最大横幅 */
margin:0 auto; /* 左右中央へ配置 */
perspective:900px; /* 立体表示の遠近感 */
transition:margin-bottom .3s ease; /* 0.3秒で下側余白を変更 */
}
/* 選択肢を開いている状態 */
.three-dimensional-select-box_field.is-open{
margin-bottom:280px; /* 選択肢を表示するための下側スペース */
}
/* 項目名 */
.three-dimensional-select-box_label{
display:block; /* ブロック要素として表示 */
margin:0 0 10px; /* 下側10pxの余白 */
color:#374151; /* 項目名の文字色 */
font-size:15px; /* 項目名の文字サイズ */
font-weight:700; /* 項目名を太字にする */
}
/* 選択中の内容を表示する見出し */
.three-dimensional-select-box_trigger{
position:relative; /* 重なり順を有効にする */
z-index:5; /* 選択肢より手前へ表示 */
display:flex; /* 文字と開閉アイコンを横並びにする */
align-items:center; /* 上下中央へ配置 */
justify-content:space-between; /* 文字とアイコンを左右へ配置 */
width:100%; /* 横幅いっぱいに表示 */
min-height:56px; /* 見出しの最小高さ */
padding:0 18px; /* 左右18pxの内側余白 */
border:1px solid #cbd5e1; /* 見出しの枠線 */
border-radius:12px; /* 見出しの角丸 */
background:#ffffff; /* 見出しの背景色 */
color:#111827; /* 見出しの文字色 */
font:inherit; /* 親要素のフォントを使用 */
font-size:16px; /* 見出しの文字サイズ */
font-weight:700; /* 見出しを太字にする */
text-align:left; /* 左揃え */
cursor:pointer; /* マウスを乗せた時にポインターを表示 */
}
/* 開閉アイコン */
.three-dimensional-select-box_arrow{
width:11px; /* アイコンの横幅 */
height:11px; /* アイコンの高さ */
margin-left:16px; /* 文字との間隔 */
border-right:3px solid #2563eb; /* アイコン右側の線 */
border-bottom:3px solid #2563eb; /* アイコン下側の線 */
transform:translateY(-3px) rotate(45deg); /* 下向きに表示 */
transition:transform .3s ease; /* 0.3秒で回転 */
}
/* 選択肢を開いている時の開閉アイコン */
.three-dimensional-select-box_field.is-open
.three-dimensional-select-box_arrow{
transform:translateY(3px) rotate(225deg); /* 上向きへ回転 */
}
/* 選択肢一覧 */
.three-dimensional-select-box_options{
position:absolute; /* 見出しの下へ重ねて配置 */
z-index:4; /* 見出しより後ろへ配置 */
top:calc(100% + 10px); /* 見出しから10px下へ配置 */
right:0; /* 右端を揃える */
left:0; /* 左端を揃える */
display:flex; /* 選択肢をflexで配置 */
flex-direction:column; /* 選択肢を縦並びにする */
gap:10px; /* 選択肢同士の間隔 */
margin:0; /* ブラウザ標準の外側余白を削除 */
padding:0; /* ブラウザ標準の内側余白を削除 */
list-style:none; /* リストマーカーを非表示 */
opacity:0; /* 閉じている時は透明 */
visibility:hidden; /* 閉じている時は非表示 */
transform-style:preserve-3d; /* 子要素の3D変形を保持 */
transform:translateY(-14px) rotateX(-12deg); /* 閉じた状態の位置と角度 */
transform-origin:top center; /* 上中央を変形の基準にする */
transition:opacity .3s ease, visibility .3s ease, transform .3s ease; /* 0.3秒で開閉 */
}
/* 選択肢を開いている状態 */
.three-dimensional-select-box_field.is-open
.three-dimensional-select-box_options{
opacity:1; /* 選択肢を表示 */
visibility:visible; /* 操作できる状態にする */
transform:translateY(0) rotateX(0deg); /* 通常位置へ移動 */
}
/* 各選択肢 */
.three-dimensional-select-box_option{
margin:0; /* ブラウザ標準の余白を削除 */
}
/* 選択肢ボタン */
.three-dimensional-select-box_option-button{
display:block; /* ブロック要素として表示 */
width:100%; /* 横幅いっぱいに表示 */
padding:15px 18px; /* 上下15px・左右18pxの内側余白 */
border:1px solid #93c5fd; /* 選択肢の枠線 */
border-radius:11px; /* 選択肢の角丸 */
background:linear-gradient(to bottom,#ffffff 0%,#eff6ff 100%); /* 立体感を付ける背景 */
box-shadow:0 4px 0 #60a5fa,0 8px 12px rgba(37,99,235,.16); /* 下側の厚みと影 */
color:#1f2937; /* 選択肢の文字色 */
font:inherit; /* 親要素のフォントを使用 */
font-size:15px; /* 選択肢の文字サイズ */
font-weight:700; /* 選択肢を太字にする */
text-align:left; /* 左揃え */
cursor:pointer; /* マウスを乗せた時にポインターを表示 */
transform:translateZ(35px) translateY(0); /* 手前へ35px浮き出して表示 */
transition:transform .18s ease, box-shadow .18s ease, background .18s ease; /* 0.18秒で変化 */
}
/* 選択肢へマウスを乗せた時 */
.three-dimensional-select-box_option-button:hover{
transform:translateZ(55px) translateY(-3px); /* さらに手前へ浮かせる */
box-shadow:0 6px 0 #2563eb,0 12px 18px rgba(37,99,235,.2); /* 厚みと影を強くする */
background:#ffffff; /* 背景を白にする */
}
/* 選択肢を押している時 */
.three-dimensional-select-box_option-button:active{
transform:translateZ(15px) translateY(3px); /* 奥へ押し込んだように表示 */
box-shadow:0 1px 0 #2563eb,0 4px 7px rgba(37,99,235,.12); /* 厚みを小さくする */
}
/* 選択中の選択肢 */
.three-dimensional-select-box_option-button.is-selected{
border-color:#2563eb; /* 枠線を青色にする */
background:linear-gradient(to bottom,#3b82f6 0%,#2563eb 100%); /* 青色の背景 */
box-shadow:0 4px 0 #1e40af,0 8px 12px rgba(37,99,235,.2); /* 濃い青色の厚みと影 */
color:#ffffff; /* 文字を白色にする */
}
/* デモ下の説明文 */
.three-dimensional-select-box_description{
margin:26px 0 0; /* 上側26pxの余白 */
color:#4b5563; /* 文字色 */
font-size:16px; /* 文字サイズ */
line-height:1.8; /* 行間 */
text-align:center; /* 中央揃え */
}
/* 画面幅640px以下 */
@media(max-width:640px){
/* セレクトボックス全体 */
.three-dimensional-select-box_wrap{
padding:28px 18px 34px; /* スマートフォンでは余白を小さくする */
}
/* 見出し */
.three-dimensional-select-box_trigger{
font-size:15px; /* スマートフォンでは文字を少し小さくする */
}
/* 選択肢一覧 */
.three-dimensional-select-box_options{
gap:8px; /* スマートフォンでは選択肢同士の間隔を小さくする */
}
}
/* 選択エリアを取得 */
const threeDimensionalSelectBoxField=
document.querySelector(
".three-dimensional-select-box_field"
);
/* 選択肢を開閉する見出しを取得 */
const threeDimensionalSelectBoxTrigger=
document.querySelector(
".three-dimensional-select-box_trigger"
);
/* 見出し内の選択中テキストを取得 */
const threeDimensionalSelectBoxValue=
document.querySelector(
".three-dimensional-select-box_value"
);
/* すべての選択肢ボタンを取得 */
const threeDimensionalSelectBoxButtons=
document.querySelectorAll(
".three-dimensional-select-box_option-button"
);
/* 見出しをクリックした時 */
threeDimensionalSelectBoxTrigger.addEventListener(
"click",
function(){
/* 選択肢の開閉状態を切り替える */
const isOpen=
threeDimensionalSelectBoxField.classList.toggle(
"is-open"
);
/* 現在の開閉状態をaria-expandedへ反映 */
threeDimensionalSelectBoxTrigger.setAttribute(
"aria-expanded",
String(isOpen)
);
}
);
/* 各選択肢へクリック処理を設定 */
threeDimensionalSelectBoxButtons.forEach(
function(button){
/* 選択肢をクリックした時 */
button.addEventListener(
"click",
function(){
/* すべての選択状態を解除 */
threeDimensionalSelectBoxButtons.forEach(
function(item){
item.classList.remove(
"is-selected"
);
}
);
/* クリックした選択肢を選択状態にする */
button.classList.add(
"is-selected"
);
/* 選択した値を取得 */
const value=
button.dataset.value;
/* 選択した内容を見出しへ反映 */
threeDimensionalSelectBoxValue.textContent=
value;
/* 100ミリ秒(0.1秒)後に選択肢を閉じる */
setTimeout(function(){
threeDimensionalSelectBoxField.classList.remove(
"is-open"
);
threeDimensionalSelectBoxTrigger.setAttribute(
"aria-expanded",
"false"
);
},100);
}
);
}
);
コードをコピーする場合
使用するコードのタブを選び、「このタブをコピー」をクリックすると、現在表示中のコードをコピーできます。
サンプル一式を取得する場合
HTML・CSSなどすべてのファイルが必要な場合は、「サンプル一式をダウンロード」をクリックしてください。
ファイル構成と設置方法
このサンプルはHTML・CSS・JavaScriptの3ファイルで構成されています。HTMLではタイトル、説明文、選択中の内容を表示する見出し、4つの選択肢を配置します。CSSでは見出し部分をフラットに表示しながら、開いた選択肢だけを手前へ浮き出すように立体表示します。JavaScriptでは見出しの開閉、選択状態の切り替え、クリックした選択肢の文字を見出しへ反映する処理を行います。
sample/
├── index.html
├── style.css
└── script.js
各ファイルの役割
index.html はセレクトボックス全体を構成するファイルです。タイトル、説明文、「お問い合わせ内容」の項目名、選択中の内容を表示する見出し、「商品について」「サービスについて」「料金について」「その他」の4つの選択肢を編集できます。選択肢を追加したい場合は、three-dimensional-select-box_optionのまとまりを同じ構成で追加できます。
style.css はセレクトボックスの見た目と立体表示を設定するファイルです。全体の横幅、余白、背景色、枠線、角丸のほか、選択肢同士の間隔、立体的な厚み、影、前後方向への移動距離、開閉アニメーションなどを変更できます。見出し部分はフラットなデザインのまま表示し、選択肢部分だけにtranslateZ()やbox-shadowを使って立体感を付けています。
script.js は選択肢の開閉と選択処理を行うファイルです。見出しをクリックするとis-openクラスを切り替え、選択肢を表示・非表示にします。選択肢をクリックすると、それまでの選択状態を解除してクリックした項目へis-selectedクラスを付け、data-valueの内容を見出しへ反映します。その後、0.1秒待って選択肢を閉じます。
設置方法・使い方
sampleフォルダへindex.html、style.css、script.jsを同じ階層で配置します。3つのファイルを保存したあと、sample/index.htmlをブラウザで開いてください。最初は「商品について」が選択された状態で表示されます。見出し部分をクリックすると4つの選択肢が立体的に開き、任意の項目をクリックすると、その項目が青色の選択状態へ切り替わり、見出し部分の文字も選択した内容へ変更されます。
カスタマイズできる内容
index.htmlではタイトル、説明文、項目名、見出しに表示する初期値、各選択肢の文章とdata-valueを変更できます。表示する選択肢の件数や順番も、HTML内の各li要素を追加・削除・並び替えることで変更できます。
style.cssでは全体の最大横幅、内側余白、背景色、枠線、角丸、見出しの高さ、選択肢同士の間隔を変更できます。選択肢の背景色、枠線、角丸、下側の厚み、影、通常時・ホバー時・クリック時の前後方向への移動距離も調整できます。また、開いている間に確保する下側スペースや開閉アニメーション時間も変更できます。
script.jsでは選択肢をクリックしてから閉じるまでの待機時間を変更できます。現在はクリック後0.1秒で閉じる設定です。
数値調整
style.css
max-width:700px;
セレクトボックス全体の最大横幅です。値を大きくすると全体が横に広がり、小さくするとコンパクトになります。
max-width:460px;
見出しと選択肢を表示する選択エリアの最大横幅です。値を変更すると見出しと各選択肢の横幅が変わります。
perspective:900px;
立体表示の遠近感を設定しています。値を変更するとtranslateZ()による奥行きの見え方が変化します。
margin-bottom:280px;
選択肢を開いたときに下側へ確保するスペースです。値を大きくすると下側の余白が広がり、小さくすると狭くなります。
transition:margin-bottom .3s ease;
開閉時に下側余白が変化する時間です。0.3秒で変化します。値を大きくするとゆっくり、小さくすると速く変化します。
top:calc(100% + 10px);
見出しと選択肢一覧の間隔です。10pxを大きくすると見出しから離れ、小さくすると近づきます。
gap:10px;
各選択肢同士の間隔です。値を大きくすると間隔が広がり、小さくすると詰まります。640px以下ではgap:8px;へ変更されます。
transform:translateY(-14px) rotateX(-12deg);
閉じている状態の選択肢一覧の位置と角度です。開くとtranslateY(0) rotateX(0deg)へ変化します。
transition:opacity .3s ease, visibility .3s ease, transform .3s ease;
選択肢一覧が開閉するときのアニメーション時間です。0.3秒で変化します。
box-shadow:0 4px 0 #60a5fa,0 8px 12px rgba(37,99,235,.16);
通常状態の選択肢に付ける厚みと影です。最初の4pxを大きくすると下側の立体的な厚みが強くなります。
transform:translateZ(35px) translateY(0);
通常状態の選択肢を手前へ35px移動して表示します。35pxを大きくするとより手前へ浮き出します。
transform:translateZ(55px) translateY(-3px);
選択肢へマウスを乗せたときの位置です。通常状態よりさらに手前へ浮き、上方向へ3px移動します。
transform:translateZ(15px) translateY(3px);
選択肢を押しているときの位置です。手前への距離を15pxまで小さくし、下へ3px移動することで押し込まれたように見せています。
script.js
setTimeout(...,100);
100は100ミリ秒、0.1秒を表します。選択肢をクリックしてから一覧を閉じるまでの待機時間です。値を大きくすると選択状態を長く見せてから閉じ、小さくすると早く閉じます。
レスポンシブ対応
このサンプルはレスポンシブ対応です。style.cssでは全体と選択エリアにwidth:100%とmax-widthを設定し、画面幅に合わせて横幅が縮小するようにしています。また、640px以下では全体のpaddingを28px 18px 34pxへ変更し、見出しの文字サイズを15px、選択肢同士の間隔を8pxへ調整しています。スマートフォン・タブレット・PCで利用できます。
コメント