納期前日でも安心! スマホのセレクトボックスはJavaScriptで書き出そう!
困ったのぅ・・・
ハメカメ師匠。
どうしたんですか?
いや・・・
実はカテゴリボタンの箇所があるのじゃが・・・
こんな感じの・・・
あー よくありますねー。
楽勝じゃないですかー。
スマホ時のデザインが後から手配されて・・・
こんな感じなんじゃ・・
な・・ な・・ なにーーーー!
スマホはセレクトボックス!?!?!?
WEBあるある夢から覚めてくれランキング6位じゃないですか!
な・・ なんじゃ そのランキングは??
フフフ・・
そんな事が納期前日に判明しても困らない・・・
よかろう
お前に今から
48の必殺WEBの一つ
「自動生成セレクトボックス」を伝授しよう!
そもそもセレクトボックスとは?
セレクトボックス(選択ボックス)は、ユーザーが複数のリストから1つの項目を選択できるようにするための要素です。
セレクトボックスは、特定の選択肢から選択を制限する必要がある場合に使用されます。 最近ではPCではボタン、スマホではセレクトボックスというUIも増えてきています。
中の森 明菜
「ボタンじゃないのよスマホは」より
自動生成セレクトボックスとは?
- ・PC時はボタン表示
- ・スマホ時はセレクトボックス表示
という仕様のUIを楽に作成できないかなと考えPC時のボタン箇所のHTMLを記述するだけでスマホ時のセレクトボックス箇所はHTMLを記述しなくて済むように
JSでボタン箇所を解析してセレクトボックスは自動で作成するというものになります。
(※勝手に命名しているだけです・・・)
これにより下記の作業が必要なくなります。
- ・セレクトボックスのマークアップ
(CSSでもちろんスタイリングはしなければならない) - ・CMS構築時にボタンとセレクトボックス2箇所に同じようにCMSタグ入れ
(カテゴリボタンの箇所だけで済みます。地味に少し面倒くさかった。)
- ※なんと今回先着100,000名様にテンプレートとなるファイルはダウンロード可能です。
- ※サンプルのソースコードは自由にお使いいただけますが、自己責任においてご使用ください。
ボタン(PC時)
一般的なお知らせページやブログページで使用されているカテゴリーボタンのHTMLとCSSになります。
HTMLの記述
<li class="state-active">
とすることでCSSでボタンがアクティブな見た目になるようにします。
HTML
コピー
<ul class="category-menu__list">
<li class="state-active"><a href="/news/"><span>すべて</span></a></li>
<li><a href="/news/info/"><span>お知らせ</span></a></li>
<li><a href="/news/press/"><span>プレス</span></a></li>
<li><a href="/news/other"><span>その他</span></a></li>
</ul>
CSSの記述
参考までに必要なCSS全記述。
お好みで自分好みのデザインにカスタマイズしてください。
必要ない方は特に難しいことはないので読み飛ばしてください。
pointer-events: none;
でイベント無効化がミソですね。
CSS
コピー
.category-menu__list {
position: relative;
z-index: 5;
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
}
.category-menu__list li {
display: inline-block;
margin-right: 10px;
margin-bottom: 10px;
position: relative;
}
@media print, screen and (min-width: 768px) {
.category-menu__list li {
margin-right: 30px;
margin-bottom: 20px;
}
}
/* ここからアクティブな状態の記述 */
.category-menu__list li.state-active a {
pointer-events: none; /* イベント無効化 */
color: #fff;
}
.category-menu__list li.state-active a span {
color: #fff;
transition: color 0.2s ease-out;
}
.category-menu__list li.state-active a::after {
transform: translateY(0);
}
/* ここまでアクティブな状態の記述 */
.category-menu__list li a {
display: flex;
flex-direction: column;
justify-content: center;
padding: 0 20px;
height: 40px;
border-radius: 20px;
overflow: hidden;
font-size: 14px;
font-weight: 700;
text-align: center;
position: relative;
}
.category-menu__list li a::before {
content: '';
position: absolute;
display: block;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #f4f4f4;
z-index: 1;
overflow: hidden;
transition: background 0.3s ease-out;
}
.category-menu__list li a::after {
content: '';
position: absolute;
display: block;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #5D5D5D;
z-index: 2;
border-radius: 20px;
overflow: hidden;
transition: transform 0.3s ease-out;
transform: translateY(101%);
}
@media print, screen and (min-width: 768px) {
.category-menu__list li a::after {
border-radius: 16px;
}
}
.category-menu__list li a span {
position: relative;
z-index: 5;
color: #5D5D5D;
transition: color 0.3s ease-out;
}
@media screen and (min-width: 1025px) {
.category-menu__list li a:hover::after {
transition: transform 0.2s ease-out;
transform: translateY(0);
}
.category-menu__list li a:hover span {
color: #fff;
transition: color 0.2s ease-out;
}
}
@media print, screen and (min-width: 768px) {
.category-menu__list li a {
padding: 0 40px;
height: 60px;
border-radius: 30px;
font-size: 18px;
}
}
セレクトボックス(SP時)
セレクトボックスのHTMLになります。
ボタンの箇所をJSで解析して下記のコードが出力されます。
HTMLの記述
ブラウザのデフォルトのセレクトボックスのデザイン(矢印・四角・テキストが左寄せなど)を変更したいので下記のような少しややこしい作りになっております。
詳細は別の記事アップ予定。
HTML
コピー
<div class="category-menu__select">
<select id="js-category-select" name="category-menu">
<option value="すべて" data-url="/news/">すべて</option>
<option value="お知らせ" data-url="/news/info/">お知らせ</option>
<option value="プレス" data-url="/news/press/">プレス</option>
<option value="その他" data-url="/news/other/">その他</option>
</select>
<label id="js-category-label">すべて</label>
</div>
CSSの記述
詳細は別の記事アップ予定ですが
取り急ぎやっていることは
- ・デフォルトのselectのスタイルを無効化
- ・selectのテキストはラベルに表示
- ・selectの矢印はafter要素で表示
になります。
参考までに必要なCSS全記述。
CSS
コピー
.category-menu__select {
width: 100%;
position: relative;
height: 40px;
}
/* select要素は opacity: 0 で非表示に */
.category-menu__select select {
position: absolute;
left: 0;
display: block;
width: 100%;
height: 100%;
z-index: 1;
opacity: 0;
}
/* select要素の代わりにlabelでテキストを表示する */
.category-menu__select label {
position: absolute;
top: 0;
left: 0;
display: flex;
flex-direction: column;
justify-content: center;
width: 100%;
height: 100%;
z-index: 2;
background: #f4f4f4;
text-align: center;
font-size: 14px;
font-weight: 700;
border-radius: 20px;
overflow: hidden;
pointer-events: none;
}
/* 矢印を表示します */
.category-menu__select::after {
position: absolute;
display: block;
content: '';
z-index: 10;
top: 50%;
width: 12px;
height: 32px;
margin-top: -16px;
right: 18px;
background: url(../img/icon_arr_btm_black.svg) center center no-repeat;
background-size: 100% auto;
transition: transform 0.3s ease-out, opacity 0.3s ease-out;
}
/* PCは非表示 */
@media print, screen and (min-width: 768px) {
.category-menu__select {
display: none;
}
}
自動生成セレクトボックスを作成しよう!
上記のボタンとセレクトボックスをもとに本題の自動生成カテゴリボタンを作成します。
HTMLの記述
ボタン箇所のHTMLを記述するだけが必要となります。
HTML
コピー
<div id="js-category-menu-assets" class="category-menu__assets state-sp-select">
<ul class="category-menu__list">
<li class="state-active"><a href="/news/"><span>すべて</span></a></li>
<li><a href="/news/info/"><span>お知らせ</span></a></li>
<li><a href="/news/press/"><span>プレス</span></a></li>
<li><a href="/news/other"><span>その他</span></a></li>
</ul>
</div>
<div id="js-category-menu-assets">
でボタン要素を囲みます。
classにstate-sp-select
があれば
PC時はボタン表示、SP時はセレクトボックス表示になります。
classにstate-sp-select
がなければ
PC時はボタン表示、SP時もボタン表示となります。
JSの記述
下記JSの全記述となります。
JS
コピー
(function() {
let activeIndex = 0;//何番目のボタンがアクティブか
let categoryLabelTxt;//セレクト要素の選択されているテキスト
const categoryMenuAssets = document.getElementById("js-category-menu-assets");
/* state-sp-selectがないとここで中止 */
if (!categoryMenuAssets.classList.contains('state-sp-select')) {
return false;
}
const categoryMenuAssetsHTML = categoryMenuAssets.innerHTML;
const categoryMenuList = categoryMenuAssets.querySelectorAll("li");
const categoryMenuListLen = categoryMenuList.length;
let selectAllSrc = '<div class="category-menu__select"><select id="js-category-select" name="category-menu">';
let optionSrc = '';
/* 初めに表示する何番目のボタンがアクティブでラベルのテキストを調べる */
for (let i = 0; i < categoryMenuListLen; i++) {
const listElem = categoryMenuList[i];
if (listElem.classList.contains('state-active')) {
activeIndex = i;
categoryLabelTxt = listElem.innerText;
break;
}
}
/* option要素を作成 */
for (let i = 0; i < categoryMenuListLen; i++) {
const listElem = categoryMenuList[i];
const listHref = listElem.querySelectorAll("a")[0].getAttribute("href");
const listText = listElem.innerText;
let listTarget = listElem.querySelectorAll("a")[0].getAttribute("target");
if (listTarget == null) listTarget = "_self";
if (i == activeIndex) {
optionSrc += '<option value="' + listText + '" data-url="' + listHref + '" data-target="' + listTarget + '" selected>' + listText + '</option>'
} else {
optionSrc += '<option value="' + listText + '" data-url="' + listHref + '" data-target="' + listTarget + '">' + listText + '</option>'
}
}
selectAllSrc += optionSrc;
selectAllSrc += '</select><label id="js-category-label">' + categoryLabelTxt + '</label></div>';
/* 元のボタンのコードをJS側で作成したセレクト要素のコードを書き出す */
categoryMenuAssets.innerHTML = categoryMenuAssetsHTML + selectAllSrc;
/*
ここからはセレクトボックスのイベント処理になります
HTMLに静的にセレクトボックスのコードを記述されていても必要な箇所になります。
*/
const categorySelect = document.getElementById("js-category-select");
const categoryLabel = document.getElementById("js-category-label");
const categorySelectOption = document.querySelectorAll("#js-category-select option");
if (categorySelect) {
categorySelect.addEventListener("change", (e) => {
const rabelTxt = categorySelect.value;
const thisNum = categorySelect.selectedIndex;
const thisOption = categorySelectOption[thisNum];
const thisHref = thisOption.getAttribute('data-url')
categoryLabel.textContent = rabelTxt;
setTimeout(function() {
window.location.href = thisHref;
}, 500);
});
}
}());
まとめ
セレクトボックス箇所をJSで書き出すと激的に楽になります。
是非一度試しに使ってみてください。
どうじゃ・・・
これで納期前日にスマホはデザイン違いのセレクトボックスが判明しても怖くあるまいて・・・
・・・
zzz・・・
・・・
やはり・・・説明が長いっす。。。
・・・す すまん・・・