ul要素やol要素で作られたリストを、スマホではselect要素に切り替えたい場面があります。カテゴリ一覧やナビゲーションなど、PCではリストで並べたいけどSPではプルダウンにまとめたいケースです。

今回は、JavaScriptでリスト要素からselect要素を自動生成し、CSSのメディアクエリで表示を切り替える方法を紹介します。

CodePen ソースコードサンプル

完成イメージ

PCではul要素のリストがそのまま表示され、SPではselect要素のプルダウンに切り替わります:

<!-- PC:リスト表示 -->
<ul id="category-list" class="sp-select-target">
  <li data-value="web">Web制作</li>
  <li data-value="css">CSS</li>
  <li data-value="js">JavaScript</li>
</ul>

<!-- SP:自動生成されるselect要素 -->
<select id="category-list-select" class="sp-select-generated">
  <option value="web">Web制作</option>
  <option value="css">CSS</option>
  <option value="js">JavaScript</option>
</select>

CSS:メディアクエリで表示切り替え

PCではselect要素を非表示、SPではリスト要素を非表示にします:

/* select要素はデフォルト非表示(PC) */
.sp-select-generated {
  display: none;
}

/* SP:リストを非表示、selectを表示 */
@media (max-width: 768px) {
  .sp-select-target {
    display: none;
  }
  .sp-select-generated {
    display: block;
  }
}

JavaScript:リストからselectを自動生成

ページ読み込み時に、対象のリスト要素からselect要素を自動生成するコードです:

function generateSelectFromList(listElement) {
  const listItems = listElement.querySelectorAll('li');
  if (listItems.length === 0) return;

  // select要素を生成
  const select = document.createElement('select');
  select.id = `${listElement.id}-select`;
  select.className = 'sp-select-generated';

  // リストアイテムからoptionを生成
  listItems.forEach(item => {
    const option = document.createElement('option');
    option.value = item.dataset.value || item.textContent.trim();
    option.textContent = item.textContent.trim();
    select.appendChild(option);
  });

  // リスト要素の直後に挿入
  listElement.parentNode.insertBefore(select, listElement.nextSibling);

  return select;
}

// .sp-select-target を持つリストを一括変換
function initSpSelects() {
  const lists = document.querySelectorAll('.sp-select-target');
  lists.forEach(list => generateSelectFromList(list));
}

document.addEventListener('DOMContentLoaded', initSpSelects);

応用:リンク付きリストの変換

リスト内のa要素からhref属性を取得し、selectの変更時にページ遷移させるパターンです。カテゴリページへのナビゲーションなどで使えます:

<ul id="nav-list" class="sp-select-target">
  <li><a href="/category/web/">Web制作</a></li>
  <li><a href="/category/css/">CSS</a></li>
  <li><a href="/category/js/">JavaScript</a></li>
</ul>
function generateSelectFromNavList(listElement) {
  const listItems = listElement.querySelectorAll('li');
  if (listItems.length === 0) return;

  const select = document.createElement('select');
  select.id = `${listElement.id}-select`;
  select.className = 'sp-select-generated';

  // デフォルトオプション
  const defaultOption = document.createElement('option');
  defaultOption.value = '';
  defaultOption.textContent = 'カテゴリを選択';
  select.appendChild(defaultOption);

  listItems.forEach(item => {
    const link = item.querySelector('a');
    const option = document.createElement('option');
    option.value = link ? link.href : '';
    option.textContent = item.textContent.trim();
    select.appendChild(option);
  });

  // 選択時にページ遷移
  select.addEventListener('change', function () {
    if (this.value) {
      window.location.href = this.value;
    }
  });

  listElement.parentNode.insertBefore(select, listElement.nextSibling);
}

// リンク付きリストを変換
document.addEventListener('DOMContentLoaded', function () {
  const navLists = document.querySelectorAll('.sp-select-target');
  navLists.forEach(list => {
    const hasLinks = list.querySelector('a');
    if (hasLinks) {
      generateSelectFromNavList(list);
    } else {
      generateSelectFromList(list);
    }
  });
});

コードの解説

ポイントは、JavaScriptでselect要素を生成し、CSSのメディアクエリで表示を制御する役割分担です。JSはあくまでDOMの生成だけを担当し、表示・非表示の切り替えはCSSに任せています。

.sp-select-targetクラスを付けたリスト要素が変換対象になります。data-value属性があればそれをoptionのvalueに、なければテキストの内容がそのままvalueになります。

応用例のリンク付きパターンでは、a要素のhref属性をoptionの値として取得し、changeイベントでwindow.location.hrefに代入することでページ遷移を実現しています。カテゴリページや固定ページへのナビゲーションをSPでプルダウン化したい場合に使えます。

まとめ

PCではリスト表示、SPではプルダウンに切り替えるレスポンシブパターンは静的サイトの制作でよく使います。CSSのメディアクエリとJavaScriptのDOM生成を組み合わせることで、HTMLの構造を変えずに対応できます。カテゴリ一覧やサイドバーのナビゲーションなど、SPで縦に場所を取りがちな要素に活用してください。