【HTML】optionタグの使い方:selectとの連携・初期値・CSS装飾

html-option-tag

HTMLのoptionタグは、フォームにおけるプルダウンメニューやリストの選択肢を作る要素です。

本記事では、基本構造や各種属性の設定方法、CSSデザインの限界、JavaScriptを用いた動的な連携、実務で役立つ知識を解説します。

目次

optionタグとは:selectタグとの書き方

Webサイトのお問い合わせフォームやアンケート画面で、ユーザーに複数の選択肢から一つ(または複数)を選んでもらう要素が「optionタグ」です。

optionタグは、単体では機能せず、親となるタグの中に配置して使用します。

フォームにおけるプルダウンメニューや選択リストを作る最小単位の部品です。

ここでは、optionタグの書き方、属性の指定方法、UX(ユーザー体験)を向上させる他タグとの使い分けを解説します。

optionタグとは:selectタグとの書き方
  • selectタグとoptionタグを組み合わせたプルダウン作成
  • option要素の属性と役割
  • プルダウンとラジオボタンの使い分け
  • datalistを使った入力候補の作成

selectタグとoptionタグを組み合わせたプルダウン作成

一般的な使い方は、selectタグという「箱」の中に、複数のoptionタグという「選択肢」を並べてプルダウンリストを作成する方法です。

プルダウンメニューを作る際は、「外枠の<select>」と「中身の<option>」をセットで記述します。

🔽 selectとoptionの基本構造

⭕️ selectで囲んでプルダウンにする

<!– 💡 select(親)と option(子)は必ずセット –>
<select name=”region”>

  <!– 💡 実務テクニック:一番上は選べない(disabled)ようにする –>
  <option value=”” disabled selected>選択してください</option>
  <option value=”tokyo”>東京都</option>
  <option value=”osaka”>大阪府</option>

</select>
HTMLコード表示
<div class="hopt-sec1-wrapper">
  <div class="hopt-sec1-demo-area">
    <div class="hopt-sec1-box">
      <div class="hopt-sec1-label">🔽 selectとoptionの基本構造</div>
      
      <div class="hopt-sec1-visual">
        <p style="font-size:12px; color:#198754; font-weight:bold; margin:0 0 5px 0;">⭕️ selectで囲んでプルダウンにする</p>
        
        <div class="hopt-sec1-mock-form">
          <label for="sampleSelect" style="font-size:12px; font-weight:bold; display:block; margin-bottom:5px;">お住まいの地域:</label>
          <select id="sampleSelect" class="hopt-sec1-select">
            <option value="" disabled selected>選択してください</option>
            <option value="tokyo">東京都</option>
            <option value="osaka">大阪府</option>
            <option value="fukuoka">福岡県</option>
          </select>
        </div>
      </div>

      <div class="hopt-sec1-code">
        <!-- 💡 select(親)と option(子)は必ずセット --><br>
        <span class="hopt-sec1-hl-blue"><select name="region"></span><br>
        <br>
          <!-- 💡 実務テクニック:一番上は選べない(disabled)ようにする --><br>
          <span class="hopt-sec1-hl-green"><option value="" disabled selected></span>選択してください<span class="hopt-sec1-hl-green"></option></span><br>
          <span class="hopt-sec1-hl-green"><option value="tokyo"></span>東京都<span class="hopt-sec1-hl-green"></option></span><br>
          <span class="hopt-sec1-hl-green"><option value="osaka"></span>大阪府<span class="hopt-sec1-hl-green"></option></span><br>
        <br>
        <span class="hopt-sec1-hl-blue"></select></span>
      </div>
    </div>
  </div>
</div>
CSSコード表示
.hopt-sec1-wrapper {
  background-color: #f8f9fa;
  padding: 20px;
  border: 1px solid #dee2e6;
  border-radius: 4px;
  font-family: sans-serif;
}
.hopt-sec1-demo-area {
  display: flex;
  justify-content: center;
}
.hopt-sec1-box {
  background-color: #ffffff;
  border: 2px dashed #adb5bd;
  padding: 25px;
  width: 100%;
  max-width: 500px;
  border-radius: 4px;
}
.hopt-sec1-label {
  font-size: 15px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #333;
}
.hopt-sec1-visual {
  background-color: #f1f3f5;
  padding: 20px;
  border-radius: 8px;
  margin-bottom: 20px;
  border: 1px solid #dee2e6;
}
.hopt-sec1-mock-form {
  background-color: #fff;
  padding: 15px;
  border-radius: 4px;
  border: 1px solid #ced4da;
}
.hopt-sec1-select {
  width: 100%;
  padding: 10px;
  border: 1px solid #ced4da;
  border-radius: 4px;
  font-size: 14px;
  color: #333;
  cursor: pointer;
}
.hopt-sec1-code {
  background-color: #282c34;
  color: #abb2bf;
  padding: 15px;
  font-family: monospace;
  font-size: 13px;
  border-radius: 4px;
  line-height: 1.6;
  border-left: 4px solid #198754;
}
.hopt-sec1-hl-green { color: #98c379; font-weight: bold; }
.hopt-sec1-hl-blue { color: #61afef; font-weight: bold; }

プルダウンメニューの作り方を詳しく知りたい人は「【HTML】プルダウン・セレクトボックス・ドロップダウンの作り方:コンボボックスとの違い」を一読ください。

option要素の属性と役割

フォームに設置したプルダウンのデータを送信し、プログラム(PHPやJavaScriptなど)で処理するには、属性を正しく設定する必要があります。

  • name属性
    送信するデータの「キー(項目名)」です。
    これは<select>タグに指定します。
  • value属性
    送信するデータの「値(中身)」です。
    これは<option>タグに指定します。

<option>タグの間に書いた日本語(例:東京都)は「ユーザーが見るための表示用テキスト」であり、サーバーに送られるのはvalue(例:tokyo)の方であるという区別を持ってください。

🗂️ value属性とname属性の正しい役割

⭕️ プルダウンを変更して裏側の「value値」を確認してください

送信されるデータ(裏側):
name=”favorite_fruit
value=”apple
<!– ❌ 致命的な間違い:optionにnameを付けている –>
<select>
  <option name=”fruit” value=”apple”>りんご</option>
</select>

<!– ⭕️ 大正解:nameはselectに、valueはoptionに! –>
<select name=”favorite_fruit”>
  <option value=”apple”>りんご</option>
  <option value=”orange”>みかん</option>
</select>
HTMLコード表示
<div class="hopt-sec2-wrapper">
  <div class="hopt-sec2-demo-area">
    <div class="hopt-sec2-box">
      <div class="hopt-sec2-label">🗂️ value属性とname属性の正しい役割</div>
      
      <div class="hopt-sec2-visual">
        <p style="font-size:12px; color:#198754; font-weight:bold; margin:0 0 5px 0;">⭕️ プルダウンを変更して裏側の「value値」を確認してください</p>
        
        <div class="hopt-sec2-mock-form">
          <select id="fruitSelect" name="favorite_fruit" class="hopt-sec2-select">
            <option value="apple">りんご</option>
            <option value="orange">みかん</option>
            <option value="grape">ぶどう</option>
          </select>
          
          <div class="hopt-sec2-result-box">
            <div style="font-size:11px; color:#666; margin-bottom:5px;">送信されるデータ(裏側):</div>
            <div style="font-family:monospace; font-size:14px; color:#0d6efd;">
              name="<span style="font-weight:bold;">favorite_fruit</span>"<br>
              value="<span id="fruitResult" style="font-weight:bold; color:#dc3545;">apple</span>"
            </div>
          </div>
        </div>
      </div>

      <div class="hopt-sec2-code">
        <!-- ❌ 致命的な間違い:optionにnameを付けている --><br>
        <select><br>
          <option <span class="hopt-sec2-hl-red">name="fruit"</span> value="apple">りんご</option><br>
        </select><br><br>

        <!-- ⭕️ 大正解:nameはselectに、valueはoptionに! --><br>
        <select <span class="hopt-sec2-hl-green">name="favorite_fruit"</span>><br>
          <option <span class="hopt-sec2-hl-blue">value="apple"</span>>りんご</option><br>
          <option <span class="hopt-sec2-hl-blue">value="orange"</span>>みかん</option><br>
        </select>
      </div>
    </div>
  </div>
</div>
CSSコード表示
.hopt-sec2-wrapper {
  background-color: #f8f9fa;
  padding: 20px;
  border: 1px solid #dee2e6;
  border-radius: 4px;
  font-family: sans-serif;
}
.hopt-sec2-demo-area {
  display: flex;
  justify-content: center;
}
.hopt-sec2-box {
  background-color: #ffffff;
  border: 2px dashed #adb5bd;
  padding: 25px;
  width: 100%;
  max-width: 500px;
  border-radius: 4px;
}
.hopt-sec2-label {
  font-size: 15px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #333;
}
.hopt-sec2-visual {
  background-color: #f1f3f5;
  padding: 20px;
  border-radius: 8px;
  margin-bottom: 20px;
  border: 1px solid #dee2e6;
}
.hopt-sec2-mock-form {
  display: flex;
  flex-direction: column;
  gap: 15px;
}
.hopt-sec2-select {
  width: 100%;
  padding: 10px;
  border: 1px solid #ced4da;
  border-radius: 4px;
  font-size: 14px;
  cursor: pointer;
}
.hopt-sec2-result-box {
  background-color: #e7f1ff;
  border: 1px dashed #0d6efd;
  padding: 15px;
  border-radius: 4px;
}
.hopt-sec2-code {
  background-color: #282c34;
  color: #abb2bf;
  padding: 15px;
  font-family: monospace;
  font-size: 13px;
  border-radius: 4px;
  line-height: 1.6;
  border-left: 4px solid #0d6efd;
}
.hopt-sec2-hl-green { color: #98c379; font-weight: bold; }
.hopt-sec2-hl-blue { color: #61afef; font-weight: bold; }
.hopt-sec2-hl-red { color: #e06c75; font-weight: bold; }
JavaScriptコード表示
setTimeout(() => {
  const fruitSelect = document.getElementById('fruitSelect');
  const fruitResult = document.getElementById('fruitResult');
  if(!fruitSelect || !fruitResult) return;

  fruitSelect.addEventListener('change', (e) => {
    fruitResult.textContent = e.target.value;
  });
}, 100);

プルダウンとラジオボタンの使い分け

HTMLフォームで「1つだけ選ぶ」UIを作る際、<select><option>を使うべきか、ラジオボタンを使うべきか、実務の現場でも議論になります。

  • ラジオボタンを使うべき場面
    選択肢が2個〜5個程度の場合。
    すべての選択肢が最初から見えているため、ユーザーが一瞬で選べます。
  • プルダウンを使うべき場面
    選択肢が6個以上の場合、または画面のスペースを節約したい場合。
🔘 UI設計:プルダウン vs ラジオボタン

【選択肢が少ない場合(例:性別)】

❌ プルダウン(操作が手間)
⭕️ ラジオボタン(1クリック)

【選択肢が多い場合(例:都道府県)】

⭕️ プルダウン(省スペース)
❌ ラジオボタン(画面を占拠)
🔘北海道 🔘青森県 🔘岩手県 🔘宮城県 🔘秋田県 🔘山形県 🔘福島県… (画面が埋め尽くされる)
<!– 💡 選択肢が2〜5個なら input type=”radio” を使う –>
<label><input type=”radio” name=”gender” value=”male”>男性</label>
<label><input type=”radio” name=”gender” value=”female”>女性</label>

<!– 💡 選択肢が6個以上なら select を使う –>
<select name=”pref”>
  <option value=”hokkaido”>北海道</option>
  <option value=”aomori”>青森県</option>
  <!– … –>
</select>
HTMLコード表示
<div class="hopt-sec3-wrapper">
  <div class="hopt-sec3-demo-area">
    <div class="hopt-sec3-box">
      <div class="hopt-sec3-label">🔘 UI設計:プルダウン vs ラジオボタン</div>
      
      <div class="hopt-sec3-visual">
        <div class="hopt-sec3-compare-block">
          <p style="font-size:13px; font-weight:bold; margin:0 0 10px 0;">【選択肢が少ない場合(例:性別)】</p>
          <div style="display:flex; gap:20px; align-items:flex-start;">
            <div style="flex:1;">
              <span style="font-size:11px; color:#dc3545; font-weight:bold;">❌ プルダウン(操作が手間)</span>
              <select class="hopt-sec3-select" style="margin-top:5px;">
                <option>男性</option><option>女性</option>
              </select>
            </div>
            <div style="flex:1;">
              <span style="font-size:11px; color:#198754; font-weight:bold;">⭕️ ラジオボタン(1クリック)</span>
              <div style="margin-top:5px; font-size:13px; display:flex; gap:10px;">
                <label><input type="radio" name="gender">男性</label>
                <label><input type="radio" name="gender">女性</label>
              </div>
            </div>
          </div>
        </div>

        <div class="hopt-sec3-compare-block" style="margin-top:20px;">
          <p style="font-size:13px; font-weight:bold; margin:0 0 10px 0;">【選択肢が多い場合(例:都道府県)】</p>
          <div style="display:flex; gap:20px; align-items:flex-start;">
            <div style="flex:1;">
              <span style="font-size:11px; color:#198754; font-weight:bold;">⭕️ プルダウン(省スペース)</span>
              <select class="hopt-sec3-select" style="margin-top:5px;">
                <option>北海道</option><option>青森県</option><option>...他45県</option>
              </select>
            </div>
            <div style="flex:1;">
              <span style="font-size:11px; color:#dc3545; font-weight:bold;">❌ ラジオボタン(画面を占拠)</span>
              <div style="margin-top:5px; font-size:11px; color:#666; border:1px dashed #ccc; padding:5px;">
                🔘北海道 🔘青森県 🔘岩手県 🔘宮城県 🔘秋田県 🔘山形県 🔘福島県... (画面が埋め尽くされる)
              </div>
            </div>
          </div>
        </div>
      </div>

      <div class="hopt-sec3-code">
        <!-- 💡 選択肢が2〜5個なら input type="radio" を使う --><br>
        <label><span class="hopt-sec3-hl-green"><input type="radio" name="gender" value="male"></span>男性</label><br>
        <label><span class="hopt-sec3-hl-green"><input type="radio" name="gender" value="female"></span>女性</label><br><br>

        <!-- 💡 選択肢が6個以上なら select を使う --><br>
        <select name="pref"><br>
          <span class="hopt-sec3-hl-blue"><option value="hokkaido"></span>北海道</option><br>
          <span class="hopt-sec3-hl-blue"><option value="aomori"></span>青森県</option><br>
          <!-- ... --><br>
        </select>
      </div>
    </div>
  </div>
</div>
CSSコード表示
.hopt-sec3-wrapper {
  background-color: #f8f9fa;
  padding: 20px;
  border: 1px solid #dee2e6;
  border-radius: 4px;
  font-family: sans-serif;
}
.hopt-sec3-demo-area {
  display: flex;
  justify-content: center;
}
.hopt-sec3-box {
  background-color: #ffffff;
  border: 2px dashed #adb5bd;
  padding: 25px;
  width: 100%;
  max-width: 550px;
  border-radius: 4px;
}
.hopt-sec3-label {
  font-size: 15px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #333;
}
.hopt-sec3-visual {
  background-color: #fff;
  padding: 0;
  margin-bottom: 20px;
}
.hopt-sec3-compare-block {
  background-color: #f8f9fa;
  border: 1px solid #dee2e6;
  padding: 15px;
  border-radius: 4px;
}
.hopt-sec3-select {
  width: 100%;
  padding: 6px;
  border: 1px solid #ced4da;
  border-radius: 4px;
  font-size: 13px;
}
.hopt-sec3-code {
  background-color: #282c34;
  color: #abb2bf;
  padding: 15px;
  font-family: monospace;
  font-size: 13px;
  border-radius: 4px;
  line-height: 1.6;
  border-left: 4px solid #198754;
}
.hopt-sec3-hl-green { color: #98c379; font-weight: bold; }
.hopt-sec3-hl-blue { color: #61afef; font-weight: bold; }

改めて、プルダウンメニューの作り方を詳しく知りたい人は「【HTML】プルダウン・セレクトボックス・ドロップダウンの作り方:コンボボックスとの違い」を一読ください。

また、ラジオボタンの作り方を詳しく知りたい人は「【HTML】ラジオボタンの作り方:1つだけ選択・name・value・checked属性の設定」を一読ください。

datalistを使った入力候補の作成

<option>タグは、<select>の中だけでなく、<datalist>という要素の中で使うことで「入力候補付きのテキスト入力欄」を作れます。

サジェスト機能を作るには、<input>list属性と<datalist>id属性を同じ名前にして紐付けます。

※なお、<datalist>の中の<option>には、通常のタグのように間にテキスト(例:<option>テキスト</option>)を書かなくても、value属性だけ指定すればサジェストとして表示されます。

⌨️ datalistによる入力候補(サジェスト)機能

⭕️ リストから選ぶことも、自由に手打ちすることも可能

※リストにない「Opera」などを自由に手打ちすることもできます。

<!– 💡 1. text入力欄を作る。list属性に任意の名前をつける –>
<input type=”text” list=”browsers”>

<!– 💡 2. datalistを作る。idをさきほどのlist名と合わせる –>
<datalist id=”browsers”>
  <!– 💡 3. optionはvalue属性だけでOK –>
  <option value=”Google Chrome”>
  <option value=”Safari”>
  <option value=”Microsoft Edge”>
</datalist>
HTMLコード表示
<div class="hopt-sec4-wrapper">
  <div class="hopt-sec4-demo-area">
    <div class="hopt-sec4-box">
      <div class="hopt-sec4-label">⌨️ datalistによる入力候補(サジェスト)機能</div>
      
      <div class="hopt-sec4-visual">
        <p style="font-size:12px; color:#0d6efd; font-weight:bold; margin:0 0 5px 0;">⭕️ リストから選ぶことも、自由に手打ちすることも可能</p>
        
        <div class="hopt-sec4-mock-form">
          <label for="browserInput" style="font-size:12px; font-weight:bold; display:block; margin-bottom:5px;">お使いのブラウザは?:</label>
          
          <input type="text" id="browserInput" list="browserList" placeholder="ダブルクリックするか入力..." class="hopt-sec4-input">
          
          <datalist id="browserList">
            <option value="Google Chrome"></option>
            <option value="Safari"></option>
            <option value="Microsoft Edge"></option>
            <option value="Firefox"></option>
          </datalist>
          
          <p style="font-size:11px; color:#666; margin-top:10px;">※リストにない「Opera」などを自由に手打ちすることもできます。</p>
        </div>
      </div>

      <div class="hopt-sec4-code">
        <!-- 💡 1. text入力欄を作る。list属性に任意の名前をつける --><br>
        <input type="text" <span class="hopt-sec4-hl-red">list="browsers"</span>><br><br>

        <!-- 💡 2. datalistを作る。idをさきほどのlist名と合わせる --><br>
        <datalist <span class="hopt-sec4-hl-red">id="browsers"</span>><br>
          <!-- 💡 3. optionはvalue属性だけでOK --><br>
          <span class="hopt-sec4-hl-green"><option value="Google Chrome"></span><br>
          <span class="hopt-sec4-hl-green"><option value="Safari"></span><br>
          <span class="hopt-sec4-hl-green"><option value="Microsoft Edge"></span><br>
        </datalist>
      </div>
    </div>
  </div>
</div>
CSSコード表示
.hopt-sec4-wrapper {
  background-color: #f8f9fa;
  padding: 20px;
  border: 1px solid #dee2e6;
  border-radius: 4px;
  font-family: sans-serif;
}
.hopt-sec4-demo-area {
  display: flex;
  justify-content: center;
}
.hopt-sec4-box {
  background-color: #ffffff;
  border: 2px dashed #adb5bd;
  padding: 25px;
  width: 100%;
  max-width: 500px;
  border-radius: 4px;
}
.hopt-sec4-label {
  font-size: 15px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #333;
}
.hopt-sec4-visual {
  background-color: #f1f3f5;
  padding: 20px;
  border-radius: 8px;
  margin-bottom: 20px;
  border: 1px solid #dee2e6;
}
.hopt-sec4-mock-form {
  background-color: #fff;
  padding: 15px;
  border-radius: 4px;
  border: 1px solid #ced4da;
}
.hopt-sec4-input {
  width: 100%;
  padding: 10px;
  border: 1px solid #ced4da;
  border-radius: 4px;
  font-size: 14px;
  color: #333;
}
.hopt-sec4-code {
  background-color: #282c34;
  color: #abb2bf;
  padding: 15px;
  font-family: monospace;
  font-size: 13px;
  border-radius: 4px;
  line-height: 1.6;
  border-left: 4px solid #0d6efd;
}
.hopt-sec4-hl-green { color: #98c379; font-weight: bold; }
.hopt-sec4-hl-red { color: #e06c75; font-weight: bold; }

選択状態をコントロール:初期値と選択不可

選択肢を並べるだけでなく、ユーザーが迷わずにフォームを入力できるように「予め特定の項目を選んでおく」、あるいは「間違った項目を選べないようにする」といったコントロールは、UI/UX設計において重要です。

ここでは、プルダウンの初期値(デフォルト)の制御、「プレースホルダー(選択してください)」の作り方、「設定したはずなのに反映されない」トラブルの解決方法を解説します。

選択状態をコントロール:初期値と選択不可
  • selectedで初期値を設定する
  • 「選択してください」を選択不可にする
  • 特定のoptionを非表示にする
  • selectedが反映されない時の原因と対処法

selectedで初期値を設定する

画面を開いた瞬間に、最初から特定の項目を選ばれた状態にするには、対象の<option>タグにselected属性を付与します。

デフォルト値を設定したい場合は、親の<select>ではなく、子要素である<option>の中にselectedを記述してください。

📌 selectedによる初期値(デフォルト)設定

⭕️ 画面を開いた時点で「クレジットカード」が選ばれている

<!– ❌ 間違い:selectタグにvalueは効かない –>
<select value=”credit”>
  <option value=”credit”>クレジットカード</option>
</select>

<!– ⭕️ 正解:選ばせておきたいoptionにselectedをつける –>
<select name=”payment”>
  <option value=”bank”>銀行振込</option>
  <option value=”credit” selected>クレジットカード</option>
  <option value=”convenience”>コンビニ決済</option>
</select>
HTMLコード表示
<div class="hopt-state1-wrapper">
  <div class="hopt-state1-demo-area">
    <div class="hopt-state1-box">
      <div class="hopt-state1-label">📌 selectedによる初期値(デフォルト)設定</div>
      
      <div class="hopt-state1-visual">
        <p style="font-size:12px; color:#198754; font-weight:bold; margin:0 0 5px 0;">⭕️ 画面を開いた時点で「クレジットカード」が選ばれている</p>
        
        <div class="hopt-state1-mock-form">
          <label style="font-size:12px; font-weight:bold; display:block; margin-bottom:5px;">お支払い方法:</label>
          <select class="hopt-state1-select">
            <option value="bank">銀行振込</option>
            <option value="credit" selected>クレジットカード</option>
            <option value="convenience">コンビニ決済</option>
          </select>
        </div>
      </div>

      <div class="hopt-state1-code">
        <!-- ❌ 間違い:selectタグにvalueは効かない --><br>
        <select <span class="hopt-state1-hl-red">value="credit"</span>><br>
          <option value="credit">クレジットカード</option><br>
        </select><br><br>

        <!-- ⭕️ 正解:選ばせておきたいoptionにselectedをつける --><br>
        <select name="payment"><br>
          <option value="bank">銀行振込</option><br>
          <option value="credit" <span class="hopt-state1-hl-green">selected</span>>クレジットカード</option><br>
          <option value="convenience">コンビニ決済</option><br>
        </select>
      </div>
    </div>
  </div>
</div>
CSSコード表示
.hopt-state1-wrapper {
  background-color: #f8f9fa;
  padding: 20px;
  border: 1px solid #dee2e6;
  border-radius: 4px;
  font-family: sans-serif;
}
.hopt-state1-demo-area {
  display: flex;
  justify-content: center;
}
.hopt-state1-box {
  background-color: #ffffff;
  border: 2px dashed #adb5bd;
  padding: 25px;
  width: 100%;
  max-width: 500px;
  border-radius: 4px;
}
.hopt-state1-label {
  font-size: 15px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #333;
}
.hopt-state1-visual {
  background-color: #f1f3f5;
  padding: 20px;
  border-radius: 8px;
  margin-bottom: 20px;
  border: 1px solid #dee2e6;
}
.hopt-state1-mock-form {
  background-color: #fff;
  padding: 15px;
  border-radius: 4px;
  border: 1px solid #ced4da;
}
.hopt-state1-select {
  width: 100%;
  padding: 10px;
  border: 1px solid #ced4da;
  border-radius: 4px;
  font-size: 14px;
  cursor: pointer;
}
.hopt-state1-code {
  background-color: #282c34;
  color: #abb2bf;
  padding: 15px;
  font-family: monospace;
  font-size: 13px;
  border-radius: 4px;
  line-height: 1.6;
  border-left: 4px solid #198754;
}
.hopt-state1-hl-green { color: #98c379; font-weight: bold; }
.hopt-state1-hl-red { color: #e06c75; font-weight: bold; }

「選択してください」を選択不可にする

フォームの一番上によくある「選択してください」という案内文があります。

これをユーザーが誤って送信しないように、選べない状態にするには、disabled属性を使用します。

プレースホルダー(案内文)として機能する最初の選択肢には、disabledselectedを同時に指定してください。

これにより「最初は表示されているけれど、一度他の項目を選んだら二度と選べない」という挙動になります。

🚫 「選択してください」を選択不可にする

⭕️ 開くと「選択してください」がグレーアウトして選べない

<!– ❌ 悪い例:誤って「選択してください」のまま送信できてしまう –>
<select>
  <option value=””>年齢層を選択してください</option>
  <!– … –>
</select>

<!– ⭕️ 良い例:初期表示はするが、項目としては選ばせない –>
<select name=”age” required>
  <!– ★ disabled(選択不可) と selected(初期表示) をセットで使う –>
  <option value=”” disabled selected>▼ 年齢層を選択してください</option>
  <option value=”20s”>20代</option>
  <option value=”30s”>30代</option>
</select>
HTMLコード表示
<div class="hopt-state2-wrapper">
  <div class="hopt-state2-demo-area">
    <div class="hopt-state2-box">
      <div class="hopt-state2-label">🚫 「選択してください」を選択不可にする</div>
      
      <div class="hopt-state2-visual">
        <p style="font-size:12px; color:#198754; font-weight:bold; margin:0 0 5px 0;">⭕️ 開くと「選択してください」がグレーアウトして選べない</p>
        
        <div class="hopt-state2-mock-form">
          <select class="hopt-state2-select">
            <option value="" disabled selected>▼ 年齢層を選択してください</option>
            <option value="20s">20代</option>
            <option value="30s">30代</option>
            <option value="40s">40代</option>
          </select>
        </div>
      </div>

      <div class="hopt-state2-code">
        <!-- ❌ 悪い例:誤って「選択してください」のまま送信できてしまう --><br>
        <select><br>
          <option value="">年齢層を選択してください</option><br>
          <!-- ... --><br>
        </select><br><br>

        <!-- ⭕️ 良い例:初期表示はするが、項目としては選ばせない --><br>
        <select name="age" required><br>
          <span class="hopt-state2-hl-comment"><!-- ★ disabled(選択不可) と selected(初期表示) をセットで使う --></span><br>
          <option value="" <span class="hopt-state2-hl-green">disabled selected</span>>▼ 年齢層を選択してください</option><br>
          <option value="20s">20代</option><br>
          <option value="30s">30代</option><br>
        </select>
      </div>
    </div>
  </div>
</div>
CSSコード表示
.hopt-state2-wrapper {
  background-color: #f8f9fa;
  padding: 20px;
  border: 1px solid #dee2e6;
  border-radius: 4px;
  font-family: sans-serif;
}
.hopt-state2-demo-area {
  display: flex;
  justify-content: center;
}
.hopt-state2-box {
  background-color: #ffffff;
  border: 2px dashed #adb5bd;
  padding: 25px;
  width: 100%;
  max-width: 500px;
  border-radius: 4px;
}
.hopt-state2-label {
  font-size: 15px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #333;
}
.hopt-state2-visual {
  background-color: #f1f3f5;
  padding: 20px;
  border-radius: 8px;
  margin-bottom: 20px;
  border: 1px solid #dee2e6;
}
.hopt-state2-mock-form {
  background-color: #fff;
  padding: 15px;
  border-radius: 4px;
  border: 1px solid #ced4da;
}
.hopt-state2-select {
  width: 100%;
  padding: 10px;
  border: 1px solid #ced4da;
  border-radius: 4px;
  font-size: 14px;
  cursor: pointer;
}
.hopt-state2-code {
  background-color: #282c34;
  color: #abb2bf;
  padding: 15px;
  font-family: monospace;
  font-size: 13px;
  border-radius: 4px;
  line-height: 1.6;
  border-left: 4px solid #198754;
}
.hopt-state2-hl-green { color: #98c379; font-weight: bold; }
.hopt-state2-hl-comment { color: #6c757d; font-style: italic; }

特定のoptionを非表示にする

「選択してください」という文字を選べなくするだけでなく、プルダウンを開いた時のリストから隠したい、特定の条件を満たした時だけ選択肢を減らしたい場合にはhidden属性を使用します。

選択肢を非表示にする場合は、CSSではなくHTML5の標準属性であるhiddenを使用してください。

プレースホルダーを整えるなら、disabled selected hiddenのセットを使うのがよいです。

👻 hidden属性で選択肢から完全に隠す

⭕️ プルダウンを開くと「選択してください」がリストに存在しない

<!– ❌ 危険:iOSのSafari等では display:none が効かずに表示される –>
<option value=”old” style=”display: none;”>廃止された部署</option>

<!– ⭕️ 完璧:HTMLの hidden 属性を使う –>
<select name=”department” required>
  <!– ★ disabled + selected + hidden の究極コンボ –>
  <option value=”” disabled selected hidden>▼ 部署を選択してください</option>
  <option value=”sales”>営業部</option>
  <option value=”dev”>開発部</option>
</select>
HTMLコード表示
<div class="hopt-state3-wrapper">
  <div class="hopt-state3-demo-area">
    <div class="hopt-state3-box">
      <div class="hopt-state3-label">👻 hidden属性で選択肢から完全に隠す</div>
      
      <div class="hopt-state3-visual">
        <p style="font-size:12px; color:#198754; font-weight:bold; margin:0 0 5px 0;">⭕️ プルダウンを開くと「選択してください」がリストに存在しない</p>
        
        <div class="hopt-state3-mock-form">
          <select class="hopt-state3-select">
            <option value="" disabled selected hidden>▼ 部署を選択してください</option>
            <option value="sales">営業部</option>
            <option value="marketing">マーケティング部</option>
            <option value="dev">開発部</option>
          </select>
        </div>
      </div>

      <div class="hopt-state3-code">
        <!-- ❌ 危険:iOSのSafari等では display:none が効かずに表示される --><br>
        <option value="old" <span class="hopt-state3-hl-red">style="display: none;"</span>>廃止された部署</option><br><br>

        <!-- ⭕️ 完璧:HTMLの hidden 属性を使う --><br>
        <select name="department" required><br>
          <span class="hopt-state3-hl-comment"><!-- ★ disabled + selected + hidden の究極コンボ --></span><br>
          <option value="" <span class="hopt-state3-hl-green">disabled selected hidden</span>>▼ 部署を選択してください</option><br>
          <option value="sales">営業部</option><br>
          <option value="dev">開発部</option><br>
        </select>
      </div>
    </div>
  </div>
</div>
CSSコード表示
.hopt-state3-wrapper {
  background-color: #f8f9fa;
  padding: 20px;
  border: 1px solid #dee2e6;
  border-radius: 4px;
  font-family: sans-serif;
}
.hopt-state3-demo-area {
  display: flex;
  justify-content: center;
}
.hopt-state3-box {
  background-color: #ffffff;
  border: 2px dashed #adb5bd;
  padding: 25px;
  width: 100%;
  max-width: 500px;
  border-radius: 4px;
}
.hopt-state3-label {
  font-size: 15px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #333;
}
.hopt-state3-visual {
  background-color: #f1f3f5;
  padding: 20px;
  border-radius: 8px;
  margin-bottom: 20px;
  border: 1px solid #dee2e6;
}
.hopt-state3-mock-form {
  background-color: #fff;
  padding: 15px;
  border-radius: 4px;
  border: 1px solid #ced4da;
}
.hopt-state3-select {
  width: 100%;
  padding: 10px;
  border: 1px solid #ced4da;
  border-radius: 4px;
  font-size: 14px;
  cursor: pointer;
}
.hopt-state3-code {
  background-color: #282c34;
  color: #abb2bf;
  padding: 15px;
  font-family: monospace;
  font-size: 13px;
  border-radius: 4px;
  line-height: 1.6;
  border-left: 4px solid #198754;
}
.hopt-state3-hl-green { color: #98c379; font-weight: bold; }
.hopt-state3-hl-red { color: #e06c75; font-weight: bold; }
.hopt-state3-hl-comment { color: #6c757d; font-style: italic; }

selectedが反映されない時の原因と対処法

「HTMLにちゃんとselectedと書いているのに、画面を見ると別のものが選ばれている」というトラブルは、実務でよく発生します。

原因は、主に以下の3つに絞られます。

  1. 複数のselectedが存在している
    <select>(複数選択不可)の中で、複数の<option>selectedがついている場合、ブラウザは一番最後に書かれているものを優先して選択します。
    PHPなどのプログラムで動的にselectedを出力している際に起こるバグです。
  2. ブラウザの強力なキャッシュ(入力履歴の保持)
    ChromeやFirefoxなどのブラウザは、ページをリロード(F5)してもユーザーが直前まで選んでいた項目を親切心で復元しようとします。
    そのため、HTMLを書き換えても画面上は変化しません。
    スーパーリロード(Ctrl + Shift + R または Cmd + Shift + R)を行うか、<form autocomplete="off">を設定します。
  3. JavaScriptがHTMLを上書きしている
    これが最も多い原因です。
    Web開発では、HTMLのselected属性よりもJavaScript側の状態が優先されます。

JavaScriptから初期値や選択状態を変更したい場合は、<option>タグのselected属性を操作するのではなく、親の<select>要素のvalueプロパティに直接値を代入するのがよいです。

🛠️ JavaScriptによる確実な選択状態の操作

⭕️ ボタンを押すと「福岡県」が強制選択されます

<!– HTML –>
<select id=”mySelect”>
  <option value=”tokyo”>東京都</option>
  <option value=”fukuoka”>福岡県</option>
</select>

/* 💡 JavaScript:optionのselectedをいじるのは悪手 */
const selectEl = document.getElementById(‘mySelect’);

// ❌ 悪い例:わざわざoptionを探してselectedを付ける(面倒でバグりやすい)
// selectEl.querySelector(‘option[value=”fukuoka”]’).selected = true;

// ⭕️ 良い例:親の select要素 の value を直接書き換える(一撃で変わる)
selectEl.value = ‘fukuoka’;
HTMLコード表示
<div class="hopt-state4-wrapper">
  <div class="hopt-state4-demo-area">
    <div class="hopt-state4-box">
      <div class="hopt-state4-label">🛠️ JavaScriptによる確実な選択状態の操作</div>
      
      <div class="hopt-state4-visual">
        <p style="font-size:12px; color:#0d6efd; font-weight:bold; margin:0 0 5px 0;">⭕️ ボタンを押すと「福岡県」が強制選択されます</p>
        
        <div class="hopt-state4-mock-form">
          <select id="jsTargetSelect" class="hopt-state4-select">
            <option value="tokyo">東京都</option>
            <option value="osaka">大阪府</option>
            <option value="fukuoka">福岡県</option>
          </select>
          <button id="btnChangeSelect" class="hopt-state4-btn" style="margin-top:10px;">JavaScriptで福岡県にする</button>
        </div>
      </div>

      <div class="hopt-state4-code">
        <!-- HTML --><br>
        <select id="mySelect"><br>
          <option value="tokyo">東京都</option><br>
          <option value="fukuoka">福岡県</option><br>
        </select><br><br>

        /* 💡 JavaScript:optionのselectedをいじるのは悪手 */<br>
        <span class="hopt-state4-hl-blue">const</span> selectEl = document.getElementById(<span class="hopt-state4-hl-green">'mySelect'</span>);<br><br>

        <span class="hopt-state4-hl-comment">// ❌ 悪い例:わざわざoptionを探してselectedを付ける(面倒でバグりやすい)</span><br>
        <span class="hopt-state4-hl-comment">// selectEl.querySelector('option[value="fukuoka"]').selected = true;</span><br><br>

        <span class="hopt-state4-hl-comment">// ⭕️ 良い例:親の select要素 の value を直接書き換える(一撃で変わる)</span><br>
        selectEl.<span class="hopt-state4-hl-red">value</span> = <span class="hopt-state4-hl-green">'fukuoka'</span>;
      </div>
    </div>
  </div>
</div>
CSSコード表示
.hopt-state4-wrapper {
  background-color: #f8f9fa;
  padding: 20px;
  border: 1px solid #dee2e6;
  border-radius: 4px;
  font-family: sans-serif;
}
.hopt-state4-demo-area {
  display: flex;
  justify-content: center;
}
.hopt-state4-box {
  background-color: #ffffff;
  border: 2px dashed #adb5bd;
  padding: 25px;
  width: 100%;
  max-width: 500px;
  border-radius: 4px;
}
.hopt-state4-label {
  font-size: 15px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #333;
}
.hopt-state4-visual {
  background-color: #f1f3f5;
  padding: 20px;
  border-radius: 8px;
  margin-bottom: 20px;
  border: 1px solid #dee2e6;
}
.hopt-state4-mock-form {
  background-color: #fff;
  padding: 15px;
  border-radius: 4px;
  border: 1px solid #ced4da;
  display: flex;
  flex-direction: column;
}
.hopt-state4-select {
  width: 100%;
  padding: 10px;
  border: 1px solid #ced4da;
  border-radius: 4px;
  font-size: 14px;
}
.hopt-state4-btn {
  background-color: #0d6efd;
  color: #fff;
  border: none;
  padding: 10px;
  border-radius: 4px;
  font-weight: bold;
  cursor: pointer;
  transition: background-color 0.2s;
}
.hopt-state4-btn:hover {
  background-color: #0b5ed7;
}
.hopt-state4-code {
  background-color: #282c34;
  color: #abb2bf;
  padding: 15px;
  font-family: monospace;
  font-size: 13px;
  border-radius: 4px;
  line-height: 1.6;
  border-left: 4px solid #0d6efd;
}
.hopt-state4-hl-green { color: #98c379; font-weight: bold; }
.hopt-state4-hl-blue { color: #61afef; font-weight: bold; }
.hopt-state4-hl-red { color: #e06c75; font-weight: bold; }
.hopt-state4-hl-comment { color: #6c757d; font-style: italic; }
JavaScriptコード表示
setTimeout(() => {
  const selectEl = document.getElementById('jsTargetSelect');
  const btn = document.getElementById('btnChangeSelect');
  if(!selectEl || !btn) return;

  btn.addEventListener('click', () => {
    // 💡 親のvalueを書き換えるだけで、画面上の選択肢も切り替わる
    selectEl.value = 'fukuoka';
  });
}, 100);

CSSでoptionタグをデザイン・装飾する

HTMLのフォームを作っていると、「プルダウンメニューのデザインをサイトに合わせてオシャレにしたい」という要望が出てきます。

しかし、<select><option>を用いた標準のプルダウンは、Webデザインにおいて「CSSでの装飾が難しい(制限が多い)要素」として開発者を悩ませています。

ここでは、ブラウザの仕様上どこまでならCSSが適用できるのかという限界を知り、その中で文字色や背景色、サイズを調整する方法、アイコン付きのプルダウンを実装する解決策を解説します。

CSSでoptionタグをデザイン・装飾する
  • optionにCSSは効きにくい?変更できるプロパティ一覧
  • 文字色と背景色の変更
  • フォントサイズ・余白・幅の調整
  • optionにアイコンや画像を入れる方法

optionにCSSは効きにくい?変更できるプロパティ一覧

プルダウンのUIは、ブラウザそのものやOSが持つネイティブ(標準)のシステムUIを使って描画される仕組みになっています。

親である<select>タグにはある程度デザインが適用できますが、中身である<option>タグに適用できるCSSは極めて限定的です。

  • ⭕️ 変更できるもの
    文字色(color)、背景色(background-color)、フォントサイズ(font-size)、フォントファミリー(font-family
  • ❌ 変更できないもの
    余白(padding, margin)、枠線(border)、角丸(border-radius)、高さ(height
🚧 optionタグへのCSS適用テスト

⚠️ selectを開いて中身のoptionを見てください

/* 💡 select(外枠)にはいろいろ効く */
select {
  padding: 10px;
  border-radius: 8px;
  border: 2px solid #0d6efd;
}

/* 💡 option(中身)には制限がある */
option {
  color: #dc3545; /* ⭕️ 効く */
  background-color: #f8d7da; /* ⭕️ 効く(※Mac Safari等では無視されることも) */
  font-size: 16px; /* ⭕️ 効く */

  padding: 20px; /* ❌ 効かない */
  border-radius: 10px; /* ❌ 効かない */
}
HTMLコード表示
<div class="hopt-css1-wrapper">
  <div class="hopt-css1-demo-area">
    <div class="hopt-css1-box">
      <div class="hopt-css1-label">🚧 optionタグへのCSS適用テスト</div>
      
      <div class="hopt-css1-visual">
        <p style="font-size:12px; color:#dc3545; font-weight:bold; margin:0 0 5px 0;">⚠️ selectを開いて中身のoptionを見てください</p>
        
        <div class="hopt-css1-mock-form">
          <select class="hopt-css1-select">
            <option class="hopt-css1-test-option">色とサイズだけ変わる(余白・角丸は無視)</option>
            <option>通常のオプション</option>
          </select>
        </div>
      </div>

      <div class="hopt-css1-code">
        /* 💡 select(外枠)にはいろいろ効く */<br>
        <span class="hopt-css1-hl-blue">select</span> {<br>
          padding: 10px;<br>
          border-radius: 8px;<br>
          border: 2px solid #0d6efd;<br>
        }<br><br>

        /* 💡 option(中身)には制限がある */<br>
        <span class="hopt-css1-hl-blue">option</span> {<br>
          <span class="hopt-css1-hl-green">color: #dc3545;</span>            /* ⭕️ 効く */<br>
          <span class="hopt-css1-hl-green">background-color: #f8d7da;</span> /* ⭕️ 効く(※Mac Safari等では無視されることも) */<br>
          <span class="hopt-css1-hl-green">font-size: 16px;</span>           /* ⭕️ 効く */<br>
        <br>
          <span class="hopt-css1-hl-red">padding: 20px;</span>             /* ❌ 効かない */<br>
          <span class="hopt-css1-hl-red">border-radius: 10px;</span>       /* ❌ 効かない */<br>
        }
      </div>
    </div>
  </div>
</div>
CSSコード表示
.hopt-css1-wrapper {
  background-color: #f8f9fa;
  padding: 20px;
  border: 1px solid #dee2e6;
  border-radius: 4px;
  font-family: sans-serif;
}
.hopt-css1-demo-area {
  display: flex;
  justify-content: center;
}
.hopt-css1-box {
  background-color: #ffffff;
  border: 2px dashed #adb5bd;
  padding: 25px;
  width: 100%;
  max-width: 500px;
  border-radius: 4px;
}
.hopt-css1-label {
  font-size: 15px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #333;
}
.hopt-css1-visual {
  background-color: #f1f3f5;
  padding: 20px;
  border-radius: 8px;
  margin-bottom: 20px;
  border: 1px solid #dee2e6;
}
.hopt-css1-mock-form {
  background-color: #fff;
  padding: 15px;
  border-radius: 4px;
}
/* 効く・効かないの検証用CSS */
.hopt-css1-select {
  width: 100%;
  padding: 10px;
  border: 2px solid #0d6efd;
  border-radius: 8px;
  font-size: 14px;
}
.hopt-css1-test-option {
  color: #dc3545;
  background-color: #f8d7da;
  font-size: 16px;
  padding: 30px; /* 無視される */
  border-radius: 20px; /* 無視される */
  border: 5px solid red; /* 無視される */
}
.hopt-css1-code {
  background-color: #282c34;
  color: #abb2bf;
  padding: 15px;
  font-family: monospace;
  font-size: 13px;
  border-radius: 4px;
  line-height: 1.6;
  border-left: 4px solid #198754;
}
.hopt-css1-hl-green { color: #98c379; font-weight: bold; }
.hopt-css1-hl-blue { color: #61afef; font-weight: bold; }
.hopt-css1-hl-red { color: #e06c75; font-weight: bold; }

文字色と背景色の変更

限定的とはいえ、選択肢ごとに文字色や背景色を変更することは可能です。

hover時の色変更はHTML/CSS単体では不可能だと割り切ることです。

初期表示の文字色や背景色は変更可能なので、「未選択(選択してください)」の項目だけグレーにし、それ以外は黒にするといった工夫でUXを向上させるのがよいです。

🎨 未選択時の文字色(グレー)の制御

⭕️ 選択を変えると色が「グレー → 黒」に変わります

/* 💡 1. プレースホルダー自体の色をグレーにする */
option[value=””] {
  color: #999;
}

/* 💡 2. 通常のoptionは黒色にする */
option:not([value=””]) {
  color: #333;
}

/* 💡 3. ★超重要:未選択の時(invalid)のselect本体をグレーにする */
select:invalid {
  color: #999;
}
HTMLコード表示
<div class="hopt-css2-wrapper">
  <div class="hopt-css2-demo-area">
    <div class="hopt-css2-box">
      <div class="hopt-css2-label">🎨 未選択時の文字色(グレー)の制御</div>
      
      <div class="hopt-css2-visual">
        <p style="font-size:12px; color:#198754; font-weight:bold; margin:0 0 5px 0;">⭕️ 選択を変えると色が「グレー → 黒」に変わります</p>
        
        <div class="hopt-css2-mock-form">
          <select class="hopt-css2-select" required>
            <option value="" disabled selected class="hopt-css2-placeholder">選択してください(グレー)</option>
            <option value="1">選択肢A(黒)</option>
            <option value="2">選択肢B(黒)</option>
          </select>
        </div>
      </div>

      <div class="hopt-css2-code">
        /* 💡 1. プレースホルダー自体の色をグレーにする */<br>
        <span class="hopt-css2-hl-blue">option[value=""]</span> {<br>
          <span class="hopt-css2-hl-green">color: #999;</span><br>
        }<br><br>

        /* 💡 2. 通常のoptionは黒色にする */<br>
        <span class="hopt-css2-hl-blue">option:not([value=""])</span> {<br>
          <span class="hopt-css2-hl-green">color: #333;</span><br>
        }<br><br>

        /* 💡 3. ★超重要:未選択の時(invalid)のselect本体をグレーにする */<br>
        <span class="hopt-css2-hl-blue">select:invalid</span> {<br>
          <span class="hopt-css2-hl-green">color: #999;</span><br>
        }
      </div>
    </div>
  </div>
</div>
CSSコード表示
.hopt-css2-wrapper {
  background-color: #f8f9fa;
  padding: 20px;
  border: 1px solid #dee2e6;
  border-radius: 4px;
  font-family: sans-serif;
}
.hopt-css2-demo-area {
  display: flex;
  justify-content: center;
}
.hopt-css2-box {
  background-color: #ffffff;
  border: 2px dashed #adb5bd;
  padding: 25px;
  width: 100%;
  max-width: 500px;
  border-radius: 4px;
}
.hopt-css2-label {
  font-size: 15px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #333;
}
.hopt-css2-visual {
  background-color: #f1f3f5;
  padding: 20px;
  border-radius: 8px;
  margin-bottom: 20px;
  border: 1px solid #dee2e6;
}
.hopt-css2-mock-form {
  background-color: #fff;
  padding: 15px;
  border-radius: 4px;
}
/* ★未選択時の色ハック */
.hopt-css2-select {
  width: 100%;
  padding: 10px;
  border: 1px solid #ced4da;
  border-radius: 4px;
  font-size: 14px;
  color: #333; /* 通常は黒 */
}
/* select要素が未選択(requiredでvalueが空)の時の文字色 */
.hopt-css2-select:invalid {
  color: #999;
}
.hopt-css2-select option {
  color: #333; /* 選択肢は黒 */
}
.hopt-css2-select option[value=""] {
  color: #999; /* プレースホルダーの選択肢はグレー */
}

.hopt-css2-code {
  background-color: #282c34;
  color: #abb2bf;
  padding: 15px;
  font-family: monospace;
  font-size: 13px;
  border-radius: 4px;
  line-height: 1.6;
  border-left: 4px solid #198754;
}
.hopt-css2-hl-green { color: #98c379; font-weight: bold; }
.hopt-css2-hl-blue { color: #61afef; font-weight: bold; }

フォントサイズ・余白・幅の調整

プルダウンの文字サイズ、クリックしやすくする余白などのサイズ調整です。

サイズや余白の調整は、すべて親要素である<select>に対して行います。

<select>widthを100%に広げ、paddingを大きくし、font-sizeを16px以上に設定することで、結果的に中身の<option>も大きく表示されてユーザーがタップしやすいUIになります。

📏 selectのサイズ調整と矢印のカスタマイズ

⭕️ selectを装飾して大きく見やすくする

/* 💡 1. 標準のダサい矢印を消す(超重要) */
select {
  appearance: none; /* ★OS標準デザインをリセット */
  width: 100%; /* 横幅いっぱい */
  padding: 15px; /* 上下左右の余白(クリックしやすく) */
  font-size: 16px; /* ★スマホでのズーム防止に必須 */
}

/* 💡 2. 親要素を使ってオシャレな矢印を付ける */
.select-wrapper {
  position: relative;
}
.select-wrapper::after {
  content: “▼”;
  position: absolute;
  right: 15px; top: 18px;
  pointer-events: none; /* ★矢印の上からでもクリック可能にする */
}
HTMLコード表示
<div class="hopt-css3-wrapper">
  <div class="hopt-css3-demo-area">
    <div class="hopt-css3-box">
      <div class="hopt-css3-label">📏 selectのサイズ調整と矢印のカスタマイズ</div>
      
      <div class="hopt-css3-visual">
        <p style="font-size:12px; color:#0d6efd; font-weight:bold; margin:0 0 5px 0;">⭕️ selectを装飾して大きく見やすくする</p>
        
        <div class="hopt-css3-mock-form">
          <div class="hopt-css3-select-wrapper">
            <select class="hopt-css3-custom-select">
              <option>タップしやすい大きなメニュー</option>
              <option>選択肢2</option>
            </select>
          </div>
        </div>
      </div>

      <div class="hopt-css3-code">
        /* 💡 1. 標準のダサい矢印を消す(超重要) */<br>
        <span class="hopt-css3-hl-blue">select</span> {<br>
          <span class="hopt-css3-hl-red">appearance: none;</span> /* ★OS標準デザインをリセット */<br>
          <span class="hopt-css3-hl-green">width: 100%;</span>        /* 横幅いっぱい */<br>
          <span class="hopt-css3-hl-green">padding: 15px;</span>      /* 上下左右の余白(クリックしやすく) */<br>
          <span class="hopt-css3-hl-green">font-size: 16px;</span>    /* ★スマホでのズーム防止に必須 */<br>
        }<br><br>

        /* 💡 2. 親要素を使ってオシャレな矢印を付ける */<br>
        <span class="hopt-css3-hl-blue">.select-wrapper</span> {<br>
          position: relative;<br>
        }<br>
        <span class="hopt-css3-hl-blue">.select-wrapper::after</span> {<br>
          content: "▼";<br>
          position: absolute;<br>
          right: 15px; top: 18px;<br>
          pointer-events: none; /* ★矢印の上からでもクリック可能にする */<br>
        }
      </div>
    </div>
  </div>
</div>
CSSコード表示
.hopt-css3-wrapper {
  background-color: #f8f9fa;
  padding: 20px;
  border: 1px solid #dee2e6;
  border-radius: 4px;
  font-family: sans-serif;
}
.hopt-css3-demo-area {
  display: flex;
  justify-content: center;
}
.hopt-css3-box {
  background-color: #ffffff;
  border: 2px dashed #adb5bd;
  padding: 25px;
  width: 100%;
  max-width: 500px;
  border-radius: 4px;
}
.hopt-css3-label {
  font-size: 15px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #333;
}
.hopt-css3-visual {
  background-color: #f1f3f5;
  padding: 20px;
  border-radius: 8px;
  margin-bottom: 20px;
  border: 1px solid #dee2e6;
}
.hopt-css3-mock-form {
  background-color: #fff;
  padding: 15px;
  border-radius: 4px;
}

/* カスタムセレクトボックスのCSS */
.hopt-css3-select-wrapper {
  position: relative;
  width: 100%;
}
/* 独自の矢印 */
.hopt-css3-select-wrapper::after {
  content: "";
  position: absolute;
  right: 15px;
  top: 50%;
  transform: translateY(-50%);
  width: 10px;
  height: 8px;
  background-color: #666;
  clip-path: polygon(100% 0%, 0 0%, 50% 100%); /* CSSで下向き三角を作る */
  pointer-events: none; /* 矢印の上からでもクリック可能に */
}
.hopt-css3-custom-select {
  appearance: none; /* OS標準デザインを消す */
  -webkit-appearance: none;
  width: 100%;
  padding: 15px 40px 15px 15px; /* 右側に矢印用の余白をあける */
  border: 2px solid #0d6efd;
  border-radius: 6px;
  font-size: 16px;
  font-weight: bold;
  background-color: #fff;
  color: #333;
  cursor: pointer;
  outline: none;
}

.hopt-css3-code {
  background-color: #282c34;
  color: #abb2bf;
  padding: 15px;
  font-family: monospace;
  font-size: 13px;
  border-radius: 4px;
  line-height: 1.6;
  border-left: 4px solid #0d6efd;
}
.hopt-css3-hl-green { color: #98c379; font-weight: bold; }
.hopt-css3-hl-blue { color: #61afef; font-weight: bold; }
.hopt-css3-hl-red { color: #e06c75; font-weight: bold; }

フォントサイズの指定方法を詳しく知りたい人は「【HTML】フォントサイズ(文字)の指定:px・rem・em・%の変更と自動調整」を一読ください。

また、余白に関する指定方法も詳しく知りたい人は「【html&css】paddingとmarginの違いは?上下左右の余白と順番」を一読ください。

optionにアイコンや画像を入れる方法

「国を選ぶプルダウンに国旗の画像を出したい」「項目名の横にアイコンを付けたい」という要望は多いです。

画像をどうしてもプルダウンに入れたい場合、アプローチは2つしかありません。

  1. 絵文字(Emoji)を使う
    画像ではなく、テキスト文字として扱われる「絵文字(🍎、🇯🇵、✅など)」を使うのが、標準HTMLで実現できる唯一にして簡単な方法です。
  2. JavaScriptでプルダウンを自作する
    実際の画像(SVGやPNG)を使いたい場合は、標準の<select>を使うことを諦め、<div><ul><li>、JavaScriptを使って「プルダウン風のカスタムUI」をゼロから構築する必要があります。
🌟 optionにアイコンを入れる唯一の標準手法

⭕️ 絵文字(テキスト)なら表示される

※ imgタグや、CSSの ::before 等による画像挿入は不可能です。

<!– ❌ 致命的な間違い:option内にHTMLタグは書けない –>
<select>
  <option><img src=”jp.png”> 日本語</option>
</select>

<!– ⭕️ 大正解:絵文字(テキスト)を使う –>
<select name=”language”>
  <option value=”ja”>🇯🇵 日本語</option>
  <option value=”en”>🇺🇸 英語</option>
  <option value=”fr”>🇫🇷 フランス語</option>
</select>
HTMLコード表示
<div class="hopt-css4-wrapper">
  <div class="hopt-css4-demo-area">
    <div class="hopt-css4-box">
      <div class="hopt-css4-label">🌟 optionにアイコンを入れる唯一の標準手法</div>
      
      <div class="hopt-css4-visual">
        <p style="font-size:12px; color:#198754; font-weight:bold; margin:0 0 5px 0;">⭕️ 絵文字(テキスト)なら表示される</p>
        
        <div class="hopt-css4-mock-form">
          <select class="hopt-css4-select">
            <option disabled selected>言語(国)を選択</option>
            <option value="ja">🇯🇵 日本語</option>
            <option value="en">🇺🇸 英語</option>
            <option value="fr">🇫🇷 フランス語</option>
          </select>
        </div>
        <p style="font-size:11px; color:#dc3545; margin-top:10px;">※ imgタグや、CSSの ::before 等による画像挿入は不可能です。</p>
      </div>

      <div class="hopt-css4-code">
        <!-- ❌ 致命的な間違い:option内にHTMLタグは書けない --><br>
        <select><br>
          <option><span class="hopt-css4-hl-red"><img src="jp.png"></span> 日本語</option><br>
        </select><br><br>

        <!-- ⭕️ 大正解:絵文字(テキスト)を使う --><br>
        <select name="language"><br>
          <option value="ja"><span class="hopt-css4-hl-green">🇯🇵</span> 日本語</option><br>
          <option value="en"><span class="hopt-css4-hl-green">🇺🇸</span> 英語</option><br>
          <option value="fr"><span class="hopt-css4-hl-green">🇫🇷</span> フランス語</option><br>
        </select>
      </div>
    </div>
  </div>
</div>
CSSコード表示
.hopt-css4-wrapper {
  background-color: #f8f9fa;
  padding: 20px;
  border: 1px solid #dee2e6;
  border-radius: 4px;
  font-family: sans-serif;
}
.hopt-css4-demo-area {
  display: flex;
  justify-content: center;
}
.hopt-css4-box {
  background-color: #ffffff;
  border: 2px dashed #adb5bd;
  padding: 25px;
  width: 100%;
  max-width: 500px;
  border-radius: 4px;
}
.hopt-css4-label {
  font-size: 15px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #333;
}
.hopt-css4-visual {
  background-color: #f1f3f5;
  padding: 20px;
  border-radius: 8px;
  margin-bottom: 20px;
  border: 1px solid #dee2e6;
}
.hopt-css4-mock-form {
  background-color: #fff;
  padding: 15px;
  border-radius: 4px;
}
.hopt-css4-select {
  width: 100%;
  padding: 10px;
  border: 1px solid #ced4da;
  border-radius: 4px;
  font-size: 16px; /* 絵文字を見やすくするため少し大きく */
  cursor: pointer;
}
.hopt-css4-code {
  background-color: #282c34;
  color: #abb2bf;
  padding: 15px;
  font-family: monospace;
  font-size: 13px;
  border-radius: 4px;
  line-height: 1.6;
  border-left: 4px solid #198754;
}
.hopt-css4-hl-green { color: #98c379; font-weight: bold; }
.hopt-css4-hl-red { color: #e06c75; font-weight: bold; }

複数選択とグループ化

HTMLの<select><option>を使ったフォーム部品は、「1つだけ選ぶ」用途に留まりません。

ユーザーに複数の項目を同時に選ばせたり、都道府県やカテゴリなど数十個に及ぶ選択肢を見やすく整理したりする機能がHTML標準で用意されています。

ここでは、フォーム要件で登場する「複数選択(マルチセレクト)」と「階層化(グループ分け)」の実装方法を解説します。

複数選択とグループ化
  • multiple属性で複数選択を実装する
  • optgroupで選択肢をグループ分けする

multiple属性で複数選択を実装する

通常のプルダウンを複数選択可能なリストに変えるには、親である<select>タグにmultiple属性を付与します。

これにより、ユーザーはCtrlキー(MacならCommandキー)やShiftキーを押しながら、複数の項目を選択できます。

複数選択を許可する場合、送信されるデータは「配列(複数のデータのまとまり)」になります。

そのため、<select>タグのname属性の末尾には、[](角カッコ)をつけてください。(例:name="fruits[]"

また、実務では「Select2」などのJavaScriptライブラリを併用してタグ付けUIにするのが一般的であることも覚えておきましょう。

☑️ multiple属性による複数選択リスト

⚠️ PCではCtrl(Cmd)キーを押しながらクリックで複数選べます

<!– ❌ 致命的な間違い:[]がないと、最後の1つしか送信されない –>
<select name=”interests” multiple>…</select>

<!– ⭕️ 大正解:複数選択の時は必ず name に [] をつける –>
<select name=”interests[]” multiple size=”4″>
  <option value=”design”>Webデザイン</option>
  <option value=”frontend”>フロントエンド開発</option>
  <option value=”backend”>バックエンド開発</option>
</select>

<!– ※ size=”4″ は最初から見せておく行数の指定です –>
HTMLコード表示
<div class="hopt-mul1-wrapper">
  
  <div class="hopt-mul1-demo-area">
    <div class="hopt-mul1-box">
      <div class="hopt-mul1-label">☑️ multiple属性による複数選択リスト</div>
      
      <div class="hopt-mul1-visual">
        <p style="font-size:12px; color:#dc3545; font-weight:bold; margin:0 0 5px 0;">⚠️ PCではCtrl(Cmd)キーを押しながらクリックで複数選べます</p>
        
        <div class="hopt-mul1-mock-form">
          <label style="font-size:12px; font-weight:bold; display:block; margin-bottom:5px;">興味のある分野(複数選択可):</label>
          <select class="hopt-mul1-select" multiple size="4">
            <option value="design">Webデザイン</option>
            <option value="frontend" selected>フロントエンド開発</option>
            <option value="backend" selected>バックエンド開発</option>
            <option value="marketing">マーケティング</option>
            <option value="seo">SEO対策</option>
          </select>
        </div>
      </div>

      <div class="hopt-mul1-code">
        <!-- ❌ 致命的な間違い:[]がないと、最後の1つしか送信されない --><br>
        <select name="interests" <span class="hopt-mul1-hl-red">multiple</span>>...</select><br><br>

        <!-- ⭕️ 大正解:複数選択の時は必ず name に [] をつける --><br>
        <select <span class="hopt-mul1-hl-green">name="interests[]"</span> <span class="hopt-mul1-hl-blue">multiple size="4"</span>><br>
          <option value="design">Webデザイン</option><br>
          <option value="frontend">フロントエンド開発</option><br>
          <option value="backend">バックエンド開発</option><br>
        </select><br><br>
        <span class="hopt-mul1-hl-comment"><!-- ※ size="4" は最初から見せておく行数の指定です --></span>
      </div>
    </div>
  </div>
</div>
CSSコード表示
.hopt-mul1-wrapper {
  background-color: #f8f9fa;
  padding: 20px;
  border: 1px solid #dee2e6;
  border-radius: 4px;
  font-family: sans-serif;
}
.hopt-mul1-demo-area {
  display: flex;
  justify-content: center;
}
.hopt-mul1-box {
  background-color: #ffffff;
  border: 2px dashed #adb5bd;
  padding: 25px;
  width: 100%;
  max-width: 500px;
  border-radius: 4px;
}
.hopt-mul1-label {
  font-size: 15px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #333;
}
.hopt-mul1-visual {
  background-color: #f1f3f5;
  padding: 20px;
  border-radius: 8px;
  margin-bottom: 20px;
  border: 1px solid #dee2e6;
}
.hopt-mul1-mock-form {
  background-color: #fff;
  padding: 15px;
  border-radius: 4px;
  border: 1px solid #ced4da;
}
.hopt-mul1-select {
  width: 100%;
  padding: 5px;
  border: 1px solid #0d6efd;
  border-radius: 4px;
  font-size: 14px;
  /* multipleの時は高さをあける */
  height: auto; 
}
.hopt-mul1-select option {
  padding: 8px;
  margin-bottom: 2px;
  border-radius: 4px;
}
.hopt-mul1-code {
  background-color: #282c34;
  color: #abb2bf;
  padding: 15px;
  font-family: monospace;
  font-size: 13px;
  border-radius: 4px;
  line-height: 1.6;
  border-left: 4px solid #198754;
}
.hopt-mul1-hl-green { color: #98c379; font-weight: bold; }
.hopt-mul1-hl-blue { color: #61afef; font-weight: bold; }
.hopt-mul1-hl-red { color: #e06c75; font-weight: bold; }
.hopt-mul1-hl-comment { color: #6c757d; font-style: italic; }

optgroupで選択肢をグループ分けする

都道府県を「関東」「関西」で分けたり、商品をカテゴリごとに整理したりするなど、選択肢を階層化して見やすくするには<optgroup>タグを使用します。

これは単一選択でも、前述の複数選択でも同様に機能します。

<optgroup>は1階層のみで使用します。

入れ子はできません。

グループの見出し(タイトル)は、<optgroup>タグのlabel属性に記述します。

このlabelの文字は太字や斜体で表示され、ユーザーがクリックして選択することはできません。

🗂️ optgroupによる選択肢のグループ化

⭕️ 開くと「エリア」で見出しがついています

<select name=”workplace” required>
  <option value=”” disabled selected hidden>選択してください</option>

  <!– 💡 optgroupタグで囲み、label属性で見出しをつける –>
  <optgroup label=”関東エリア”>
    <option value=”tokyo”>東京都</option>
    <option value=”kanagawa”>神奈川県</option>
  </optgroup>

  <optgroup label=”関西エリア”>
    <option value=”osaka”>大阪府</option>
    <option value=”kyoto”>京都府</option>
  </optgroup>
</select>
    HTMLコード表示
    <div class="hopt-mul2-wrapper">
      <div class="hopt-mul2-demo-area">
        <div class="hopt-mul2-box">
          <div class="hopt-mul2-label">🗂️ optgroupによる選択肢のグループ化</div>
          
          <div class="hopt-mul2-visual">
            <p style="font-size:12px; color:#198754; font-weight:bold; margin:0 0 5px 0;">⭕️ 開くと「エリア」で見出しがついています</p>
            
            <div class="hopt-mul2-mock-form">
              <label style="font-size:12px; font-weight:bold; display:block; margin-bottom:5px;">ご希望の勤務地:</label>
              <select class="hopt-mul2-select">
                <option value="" disabled selected hidden>勤務地を選択してください</option>
                
                <optgroup label="■ 関東エリア">
                  <option value="tokyo">東京都</option>
                  <option value="kanagawa">神奈川県</option>
                  <option value="saitama">埼玉県</option>
                </optgroup>
                
                <optgroup label="■ 関西エリア">
                  <option value="osaka">大阪府</option>
                  <option value="kyoto">京都府</option>
                  <option value="hyogo">兵庫県</option>
                </optgroup>
              </select>
            </div>
          </div>
    
          <div class="hopt-mul2-code">
            <select name="workplace" required><br>
              <option value="" disabled selected hidden>選択してください</option><br><br>
    
              <!-- 💡 optgroupタグで囲み、label属性で見出しをつける --><br>
              <span class="hopt-mul2-hl-blue"><optgroup <span class="hopt-mul2-hl-green">label="関東エリア"</span>></span><br>
                <option value="tokyo">東京都</option><br>
                <option value="kanagawa">神奈川県</option><br>
              <span class="hopt-mul2-hl-blue"></optgroup></span><br><br>
    
              <span class="hopt-mul2-hl-blue"><optgroup <span class="hopt-mul2-hl-green">label="関西エリア"</span>></span><br>
                <option value="osaka">大阪府</option><br>
                <option value="kyoto">京都府</option><br>
              <span class="hopt-mul2-hl-blue"></optgroup></span><br>
            </select>
          </div>
        </div>
      </div>
    </div>
    CSSコード表示
    .hopt-mul2-wrapper {
      background-color: #f8f9fa;
      padding: 20px;
      border: 1px solid #dee2e6;
      border-radius: 4px;
      font-family: sans-serif;
    }
    .hopt-mul2-demo-area {
      display: flex;
      justify-content: center;
    }
    .hopt-mul2-box {
      background-color: #ffffff;
      border: 2px dashed #adb5bd;
      padding: 25px;
      width: 100%;
      max-width: 500px;
      border-radius: 4px;
    }
    .hopt-mul2-label {
      font-size: 15px;
      font-weight: bold;
      margin-bottom: 20px;
      color: #333;
    }
    .hopt-mul2-visual {
      background-color: #f1f3f5;
      padding: 20px;
      border-radius: 8px;
      margin-bottom: 20px;
      border: 1px solid #dee2e6;
    }
    .hopt-mul2-mock-form {
      background-color: #fff;
      padding: 15px;
      border-radius: 4px;
      border: 1px solid #ced4da;
    }
    .hopt-mul2-select {
      width: 100%;
      padding: 10px;
      border: 1px solid #ced4da;
      border-radius: 4px;
      font-size: 14px;
      cursor: pointer;
    }
    /* optgroupのラベルはブラウザ側で自動的に太字等になります */
    .hopt-mul2-select optgroup {
      font-weight: bold;
      color: #0d6efd;
      font-style: normal;
    }
    .hopt-mul2-select option {
      color: #333;
      padding: 5px;
    }
    .hopt-mul2-code {
      background-color: #282c34;
      color: #abb2bf;
      padding: 15px;
      font-family: monospace;
      font-size: 13px;
      border-radius: 4px;
      line-height: 1.6;
      border-left: 4px solid #198754;
    }
    .hopt-mul2-hl-green { color: #98c379; font-weight: bold; }
    .hopt-mul2-hl-blue { color: #61afef; font-weight: bold; }

    JavaScriptを使った動的なoption操作とイベント連携

    HTMLとCSSでフォームの見た目を整えた後は、JavaScriptを組み合わせて、ユーザーの操作に応じた動的な動きを追加していくフェーズに入ります。

    「都道府県を選ぶと、その下の市区町村の選択肢が自動で切り替わる」「選択した商品の値段を即座に計算して表示する」といった機能は、JavaScriptによるDOM操作とイベント連携によって実現されます。

    ここでは、値の取得、要素の動的な生成、イベント発火のバグと回避策を解説します。

    JavaScriptを使った動的なoption操作とイベント連携
    • 選択された値を取得する
    • JSでoptionを動的に追加・削除する
    • onclickonselectイベントの注意点と代替案
    • data属性を使った複数データの保持と活用

    選択された値を取得する

    プルダウンでユーザーが項目を選んだ瞬間に値を取得し、画面上に表示したり計算を走らせたりする処理は、すべての基本となります。

    この値の取得のタイミングを検知するには、changeイベントを使用します。

    値を取得する場合は、個別の<option>を探す必要はありません。

    親要素である<select>タグそのもののvalueプロパティ(selectElement.value)にアクセスするだけで、選ばれている<option>の値が取得できます。

    🔄 選択された値の取得(changeイベント)

    ⭕️ 選択を変えると、即座に裏側のプログラムが値を検知します

    取得した値: (未選択)
    <!– HTML –>
    <select id=”mySelect”>…</select>

    /* 💡 JavaScript */
    const selectEl = document.getElementById(‘mySelect’);

    // ★ 値が変わった瞬間(change)に処理を実行する
    selectEl.addEventListener(‘change’, (event) => {

      // ❌ 悪い例:わざわざoptionを探してループする(不要)

      // ⭕️ 良い例:select本体から一発で取得する
      const selectedValue = event.target.value;

      console.log(“選ばれた値は: ” + selectedValue);
    });
    HTMLコード表示
    <div class="hopt-js1-wrapper">
      
      <div class="hopt-js1-demo-area">
        <div class="hopt-js1-box">
          <div class="hopt-js1-label">🔄 選択された値の取得(changeイベント)</div>
          
          <div class="hopt-js1-visual">
            <p style="font-size:12px; color:#198754; font-weight:bold; margin:0 0 5px 0;">⭕️ 選択を変えると、即座に裏側のプログラムが値を検知します</p>
            
            <div class="hopt-js1-mock-form">
              <select id="colorSelect" class="hopt-js1-select">
                <option value="" disabled selected>好きな色を選択</option>
                <option value="red">赤色</option>
                <option value="blue">青色</option>
                <option value="green">緑色</option>
              </select>
              
              <div class="hopt-js1-result">
                取得した値: <span id="colorResult" style="font-weight:bold; color:#0d6efd;">(未選択)</span>
              </div>
            </div>
          </div>
    
          <div class="hopt-js1-code">
            <!-- HTML --><br>
            <select id="mySelect">...</select><br><br>
    
            /* 💡 JavaScript */<br>
            <span class="hopt-js1-hl-blue">const</span> selectEl = document.getElementById(<span class="hopt-js1-hl-green">'mySelect'</span>);<br><br>
    
            <span class="hopt-js1-hl-comment">// ★ 値が変わった瞬間(change)に処理を実行する</span><br>
            selectEl.addEventListener(<span class="hopt-js1-hl-red">'change'</span>, (event) => {<br>
            <br>
              <span class="hopt-js1-hl-comment">// ❌ 悪い例:わざわざoptionを探してループする(不要)</span><br><br>
    
              <span class="hopt-js1-hl-comment">// ⭕️ 良い例:select本体から一発で取得する</span><br>
              <span class="hopt-js1-hl-blue">const</span> selectedValue = <span class="hopt-js1-hl-green">event.target.value</span>;<br>
            <br>
              console.log("選ばれた値は: " + selectedValue);<br>
            });
          </div>
        </div>
      </div>
    </div>
    CSSコード表示
    .hopt-js1-wrapper {
      background-color: #f8f9fa;
      padding: 20px;
      border: 1px solid #dee2e6;
      border-radius: 4px;
      font-family: sans-serif;
    }
    
    .hopt-js1-demo-area {
      display: flex;
      justify-content: center;
    }
    
    .hopt-js1-box {
      background-color: #ffffff;
      border: 2px dashed #adb5bd;
      padding: 25px;
      width: 100%;
      max-width: 500px;
      border-radius: 4px;
    }
    
    .hopt-js1-label {
      font-size: 15px;
      font-weight: bold;
      margin-bottom: 20px;
      color: #333;
    }
    
    .hopt-js1-visual {
      background-color: #f1f3f5;
      padding: 20px;
      border-radius: 8px;
      margin-bottom: 20px;
      border: 1px solid #dee2e6;
    }
    
    .hopt-js1-mock-form {
      background-color: #fff;
      padding: 15px;
      border-radius: 4px;
      display: flex;
      flex-direction: column;
      gap: 15px;
    }
    
    .hopt-js1-select {
      width: 100%;
      padding: 10px;
      border: 1px solid #ced4da;
      border-radius: 4px;
      font-size: 14px;
      cursor: pointer;
    }
    
    .hopt-js1-result {
      background-color: #e9ecef;
      padding: 10px;
      border-radius: 4px;
      font-size: 13px;
      text-align: center;
    }
    
    .hopt-js1-code {
      background-color: #282c34;
      color: #abb2bf;
      padding: 15px;
      font-family: monospace;
      font-size: 13px;
      border-radius: 4px;
      line-height: 1.6;
      border-left: 4px solid #198754;
    }
    
    .hopt-js1-hl-green {
      color: #98c379;
      font-weight: bold;
    }
    
    .hopt-js1-hl-blue {
      color: #61afef;
      font-weight: bold;
    }
    
    .hopt-js1-hl-red {
      color: #e06c75;
      font-weight: bold;
    }
    
    .hopt-js1-hl-comment {
      color: #6c757d;
      font-style: italic;
    }
    JavaScriptコード表示
    setTimeout(() => {
      const colorSelect = document.getElementById('colorSelect');
      const colorResult = document.getElementById('colorResult');
      if(colorSelect && colorResult) {
        colorSelect.addEventListener('change', (e) => {
          colorResult.textContent = e.target.value;
        });
      }
    }, 100);

    JSでoptionを動的に追加・削除する

    「大カテゴリ(例:果物)」を選ぶと、隣の小カテゴリのプルダウンに「りんご、みかん…」という選択肢が自動で生成される機能は、実務でよく実装します。

    これには、JavaScriptを使って選択肢を動的に追加したり、削除したりする処理が必要です。

    • 追加する時
      DOM APIのnew Option("表示テキスト", "value値")を使って要素を作成し、selectElement.appendChild()またはselectElement.add()で追加します。
    • 初期化(削除)する時
      古い選択肢を消す場合は、innerHTML = ""を使うか、selectElement.options.length = 0と記述して中身を空っぽにします。
    ✨ optionの動的な追加と削除(連動プルダウン)

    ⭕️ 左側のカテゴリを変えると、右側の中身が動的に生成されます

    /* 💡 準備:追加したいデータ */
    const data = {
      fruits: [{ text: ‘りんご’, val: ‘apple’ }, { text: ‘みかん’, val: ‘orange’ }],
      cars: [{ text: ‘セダン’, val: ‘sedan’ }, { text: ‘SUV’, val: ‘suv’ }]
    };

    /* 💡 変更を検知して動的に生成する */
    catSelect.addEventListener(‘change’, (e) => {
      const items = data[e.target.value];

      // 1. 古い中身をすべて削除(リセット)
      subSelect.options.length = 0;

      // 2. 新しいoptionをループで作って追加
      items.forEach(item => {
        // ★ new Option(表示テキスト, value値)
        const newOpt = new Option(item.text, item.val);
        subSelect.add(newOpt);
      });
    });
    HTMLコード表示
    <div class="hopt-js2-wrapper">
      
      <div class="hopt-js2-demo-area">
        <div class="hopt-js2-box">
          <div class="hopt-js2-label">✨ optionの動的な追加と削除(連動プルダウン)</div>
          
          <div class="hopt-js2-visual">
            <p style="font-size:12px; color:#0d6efd; font-weight:bold; margin:0 0 5px 0;">⭕️ 左側のカテゴリを変えると、右側の中身が動的に生成されます</p>
            
            <div class="hopt-js2-mock-form">
              <div style="flex:1;">
                <label style="font-size:11px; font-weight:bold;">大カテゴリ</label>
                <select id="catSelect" class="hopt-js2-select">
                  <option value="" disabled selected>選択してください</option>
                  <option value="fruits">果物</option>
                  <option value="cars">自動車</option>
                </select>
              </div>
              <div style="flex:1;">
                <label style="font-size:11px; font-weight:bold;">小カテゴリ</label>
                <select id="subSelect" class="hopt-js2-select" disabled>
                  <option value="">(先に大カテゴリを選んでください)</option>
                </select>
              </div>
            </div>
          </div>
    
          <div class="hopt-js2-code">
            /* 💡 準備:追加したいデータ */<br>
            <span class="hopt-js2-hl-blue">const</span> data = {<br>
              fruits: [{ text: 'りんご', val: 'apple' }, { text: 'みかん', val: 'orange' }],<br>
              cars: [{ text: 'セダン', val: 'sedan' }, { text: 'SUV', val: 'suv' }]<br>
            };<br><br>
    
            /* 💡 変更を検知して動的に生成する */<br>
            catSelect.addEventListener('change', (e) => {<br>
              <span class="hopt-js2-hl-blue">const</span> items = data[e.target.value];<br><br>
    
              <span class="hopt-js2-hl-comment">// 1. 古い中身をすべて削除(リセット)</span><br>
              subSelect.<span class="hopt-js2-hl-red">options.length = 0;</span><br><br>
    
              <span class="hopt-js2-hl-comment">// 2. 新しいoptionをループで作って追加</span><br>
              items.forEach(item => {<br>
                <span class="hopt-js2-hl-comment">// ★ new Option(表示テキスト, value値)</span><br>
                <span class="hopt-js2-hl-blue">const</span> newOpt = <span class="hopt-js2-hl-green">new Option</span>(item.text, item.val);<br>
                subSelect.<span class="hopt-js2-hl-green">add</span>(newOpt);<br>
              });<br>
            });
          </div>
        </div>
      </div>
    </div>
    CSSコード表示
    .hopt-js2-wrapper {
      background-color: #f8f9fa;
      padding: 20px;
      border: 1px solid #dee2e6;
      border-radius: 4px;
      font-family: sans-serif;
    }
    
    .hopt-js2-demo-area {
      display: flex;
      justify-content: center;
    }
    
    .hopt-js2-box {
      background-color: #ffffff;
      border: 2px dashed #adb5bd;
      padding: 25px;
      width: 100%;
      max-width: 550px;
      border-radius: 4px;
    }
    
    .hopt-js2-label {
      font-size: 15px;
      font-weight: bold;
      margin-bottom: 20px;
      color: #333;
    }
    
    .hopt-js2-visual {
      background-color: #f1f3f5;
      padding: 20px;
      border-radius: 8px;
      margin-bottom: 20px;
      border: 1px solid #dee2e6;
    }
    
    .hopt-js2-mock-form {
      background-color: #fff;
      padding: 15px;
      border-radius: 4px;
      display: flex;
      gap: 10px;
    }
    
    .hopt-js2-select {
      width: 100%;
      padding: 8px;
      border: 1px solid #ced4da;
      border-radius: 4px;
      font-size: 13px;
    }
    
    .hopt-js2-select:disabled {
      background-color: #e9ecef;
      cursor: not-allowed;
    }
    
    .hopt-js2-code {
      background-color: #282c34;
      color: #abb2bf;
      padding: 15px;
      font-family: monospace;
      font-size: 13px;
      border-radius: 4px;
      line-height: 1.6;
      border-left: 4px solid #0d6efd;
    }
    
    .hopt-js2-hl-green {
      color: #98c379;
      font-weight: bold;
    }
    
    .hopt-js2-hl-blue {
      color: #61afef;
      font-weight: bold;
    }
    
    .hopt-js2-hl-red {
      color: #e06c75;
      font-weight: bold;
    }
    
    .hopt-js2-hl-comment {
      color: #6c757d;
      font-style: italic;
    }
    JavaScriptコード表示
    setTimeout(() => {
      const cat = document.getElementById('catSelect');
      const sub = document.getElementById('subSelect');
      const dummyData = {
        fruits: [{t:'りんご', v:'apple'}, {t:'みかん', v:'orange'}, {t:'ぶどう', v:'grape'}],
        cars: [{t:'セダン', v:'sedan'}, {t:'SUV', v:'suv'}, {t:'トラック', v:'truck'}]
      };
      if(cat && sub) {
        cat.addEventListener('change', (e) => {
          const items = dummyData[e.target.value];
          sub.options.length = 0; // reset
          items.forEach(item => sub.add(new Option(item.t, item.v)));
          sub.disabled = false;
        });
      }
    }, 100);

    onclickやonselectイベントの注意点と代替案

    「選択肢がクリックされた瞬間に処理を走らせたい」と考えた時、<option>タグに対してクリックイベントを仕掛けようとします。

    <option>要素に対する直接のイベント付与は避けなければなりません。

    ユーザーの選択操作を検知したい場合は、親要素である<select>に対してchangeイベントを設定するのが唯一の代替案です。

    ⚠️ onclickの罠と正しい代替案(change)

    ❌ スマホで動かなくなる致命的なバグの原因

    <option onclick=”alert()”> などの直接付与は、
    iPhone等のモバイルブラウザで無視されます。
    <!– ❌ 危険なコード:optionに直接onclickを書いている –>
    <select>
      <option onclick=”calcPrice()”>プランA</option>
      <option onclick=”calcPrice()”>プランB</option>
    </select>

    <!– ⭕️ 安全な代替案:selectタグに一括してchangeイベントを設定する –>
    <select id=”planSelect”>
      <option value=”A”>プランA</option>
      <option value=”B”>プランB</option>
    </select>

    <script>
    // JS側で「親タグ」の「変更」を監視する
    document.getElementById(‘planSelect’).addEventListener(‘change’, (e) => {
      // ここで calcPrice() などの処理を実行する
    });
    </script>
    HTMLコード表示
    <div class="hopt-js3-wrapper">
      
      <div class="hopt-js3-demo-area">
        <div class="hopt-js3-box">
          <div class="hopt-js3-label">⚠️ onclickの罠と正しい代替案(change)</div>
          
          <div class="hopt-js3-visual">
            <p style="font-size:12px; color:#dc3545; font-weight:bold; margin:0 0 5px 0;">❌ スマホで動かなくなる致命的なバグの原因</p>
            <div style="background:#f8d7da; border:1px solid #f5c2c7; padding:10px; border-radius:4px; font-size:12px; color:#842029;">
              <option <span style="font-weight:bold;">onclick="alert()"</span>> などの直接付与は、<br>
              iPhone等のモバイルブラウザで無視されます。
            </div>
          </div>
    
          <div class="hopt-js3-code">
            <!-- ❌ 危険なコード:optionに直接onclickを書いている --><br>
            <select><br>
              <option <span class="hopt-js3-hl-red">onclick="calcPrice()"</span>>プランA</option><br>
              <option <span class="hopt-js3-hl-red">onclick="calcPrice()"</span>>プランB</option><br>
            </select><br><br>
    
            <!-- ⭕️ 安全な代替案:selectタグに一括してchangeイベントを設定する --><br>
            <select <span class="hopt-js3-hl-green">id="planSelect"</span>><br>
              <option value="A">プランA</option><br>
              <option value="B">プランB</option><br>
            </select><br><br>
    
            <script><br>
            <span class="hopt-js3-hl-comment">// JS側で「親タグ」の「変更」を監視する</span><br>
            document.getElementById('planSelect').<span class="hopt-js3-hl-blue">addEventListener('change'</span>, (e) => {<br>
              <span class="hopt-js3-hl-comment">// ここで calcPrice() などの処理を実行する</span><br>
            });<br>
            </script>
          </div>
        </div>
      </div>
    </div>
    CSSコード表示
    .hopt-js3-wrapper {
      background-color: #f8f9fa;
      padding: 20px;
      border: 1px solid #dee2e6;
      border-radius: 4px;
      font-family: sans-serif;
    }
    
    .hopt-js3-demo-area {
      display: flex;
      justify-content: center;
    }
    
    .hopt-js3-box {
      background-color: #ffffff;
      border: 2px dashed #adb5bd;
      padding: 25px;
      width: 100%;
      max-width: 500px;
      border-radius: 4px;
    }
    
    .hopt-js3-label {
      font-size: 15px;
      font-weight: bold;
      margin-bottom: 20px;
      color: #333;
    }
    
    .hopt-js3-visual {
      background-color: #f1f3f5;
      padding: 15px;
      border-radius: 8px;
      margin-bottom: 20px;
      border: 1px solid #dee2e6;
    }
    
    .hopt-js3-code {
      background-color: #282c34;
      color: #abb2bf;
      padding: 15px;
      font-family: monospace;
      font-size: 13px;
      border-radius: 4px;
      line-height: 1.6;
      border-left: 4px solid #dc3545;
    }
    
    .hopt-js3-hl-green {
      color: #98c379;
      font-weight: bold;
    }
    
    .hopt-js3-hl-blue {
      color: #61afef;
      font-weight: bold;
    }
    
    .hopt-js3-hl-red {
      color: #e06c75;
      font-weight: bold;
    }
    
    .hopt-js3-hl-comment {
      color: #6c757d;
      font-style: italic;
    }

    data-*属性を使った複数データの保持と活用

    実務でフォームを作っていると、「プルダウンで選ばれた商品のvalueだけでなく、一緒に『金額』や『カテゴリ名』などの付加情報も取得して画面に表示させたい」という要件に直面します。

    HTML5から導入されたdata-*属性(カスタムデータ属性)を活用してください。

    <option value="item01" data-price="1000" data-category="food">のように設定することで、HTMLを汚さずに複数のデータを独立して保持できます。

    🏷️ data属性を使った複数データの保持

    ⭕️ value(ID)とは別に、裏側に隠した「金額」を取得する

    選択中の料金: ¥0
    <!– HTML:valueにはIDを、data-priceには金額を入れる –>
    <select id=”mySelect”>
      <option value=”A001″ data-price=”1200″>プランA</option>
    </select>

    /* 💡 JavaScript:選ばれたoptionの data-price を取得する */
    selectEl.addEventListener(‘change’, (e) => {
      // ★少し長いが、実務で必須の取得構文
      const selectedOption = e.target.options[e.target.selectedIndex];

      // .dataset.price で data-price の中身にアクセスできる
      const price = selectedOption.dataset.price;

      console.log(“金額は: ” + price + “円”);
    });
    HTMLコード表示
    <div class="hopt-js4-wrapper">
      <div class="hopt-js4-demo-area">
        <div class="hopt-js4-box">
          <div class="hopt-js4-label">🏷️ data属性を使った複数データの保持</div>
          
          <div class="hopt-js4-visual">
            <p style="font-size:12px; color:#198754; font-weight:bold; margin:0 0 5px 0;">⭕️ value(ID)とは別に、裏側に隠した「金額」を取得する</p>
            
            <div class="hopt-js4-mock-form">
              <select id="productSelect" class="hopt-js4-select">
                <option value="" disabled selected>商品を選択</option>
                <option value="A001" data-price="1200">スタンダードプラン</option>
                <option value="A002" data-price="2500">プレミアムプラン</option>
              </select>
              <div class="hopt-js4-result-box">
                選択中の料金: <span id="priceResult" style="color:#dc3545; font-weight:bold; font-size:16px;">¥0</span>
              </div>
            </div>
          </div>
    
          <div class="hopt-js4-code">
            <!-- HTML:valueにはIDを、data-priceには金額を入れる --><br>
            <select id="mySelect"><br>
              <option value="A001" <span class="hopt-js4-hl-red">data-price="1200"</span>>プランA</option><br>
            </select><br><br>
    
            /* 💡 JavaScript:選ばれたoptionの data-price を取得する */<br>
            selectEl.addEventListener('change', (e) => {<br>
              <span class="hopt-js4-hl-comment">// ★少し長いが、実務で必須の取得構文</span><br>
              <span class="hopt-js4-hl-blue">const</span> selectedOption = e.target.options[<span class="hopt-js4-hl-green">e.target.selectedIndex</span>];<br><br>
            
              <span class="hopt-js4-hl-comment">// .dataset.price で data-price の中身にアクセスできる</span><br>
              <span class="hopt-js4-hl-blue">const</span> price = selectedOption.<span class="hopt-js4-hl-red">dataset.price</span>;<br>
            <br>
              console.log("金額は: " + price + "円");<br>
            });
          </div>
        </div>
      </div>
    </div>
    CSSコード表示
    .hopt-js4-wrapper {
      background-color: #f8f9fa;
      padding: 20px;
      border: 1px solid #dee2e6;
      border-radius: 4px;
      font-family: sans-serif;
    }
    
    .hopt-js4-demo-area {
      display: flex;
      justify-content: center;
    }
    
    .hopt-js4-box {
      background-color: #ffffff;
      border: 2px dashed #adb5bd;
      padding: 25px;
      width: 100%;
      max-width: 550px;
      border-radius: 4px;
    }
    
    .hopt-js4-label {
      font-size: 15px;
      font-weight: bold;
      margin-bottom: 20px;
      color: #333;
    }
    
    .hopt-js4-visual {
      background-color: #f1f3f5;
      padding: 20px;
      border-radius: 8px;
      margin-bottom: 20px;
      border: 1px solid #dee2e6;
    }
    
    .hopt-js4-mock-form {
      background-color: #fff;
      padding: 15px;
      border-radius: 4px;
      display: flex;
      flex-direction: column;
      gap: 15px;
    }
    
    .hopt-js4-select {
      width: 100%;
      padding: 10px;
      border: 1px solid #ced4da;
      border-radius: 4px;
      font-size: 14px;
      cursor: pointer;
    }
    
    .hopt-js4-result-box {
      background-color: #e7f1ff;
      padding: 15px;
      border: 1px dashed #0d6efd;
      border-radius: 4px;
      text-align: center;
      font-size: 13px;
    }
    
    .hopt-js4-code {
      background-color: #282c34;
      color: #abb2bf;
      padding: 15px;
      font-family: monospace;
      font-size: 13px;
      border-radius: 4px;
      line-height: 1.6;
      border-left: 4px solid #198754;
    }
    
    .hopt-js4-hl-green {
      color: #98c379;
      font-weight: bold;
    }
    
    .hopt-js4-hl-blue {
      color: #61afef;
      font-weight: bold;
    }
    
    .hopt-js4-hl-red {
      color: #e06c75;
      font-weight: bold;
    }
    
    .hopt-js4-hl-comment {
      color: #6c757d;
      font-style: italic;
    }

    まとめ

    分かりやすいようにまとめを記載します。

    本記事のまとめ
    • 基本構造
      optionタグは単体では機能せず、<select><datalist>の子要素として配置する。
    • 属性の役割
      データの送信値はoptionvalue属性に、送信キーは親であるselectname属性に設定する。
    • 初期状態の制御
      初期値にはselected、選択不可にはdisabled、リストからの非表示にはhiddenを指定する。
    • プレースホルダー
      一番上の「選択してください」はvalue="" disabled selected hiddenの組み合わせで実装する。
    • UIの最適化
      選択肢が5個以下の場合はラジオボタンを推奨し、自由なテキスト入力も許可したい場合は<datalist>を活用する。
    • 複数選択・グループ化
      親のmultiple属性で複数選択を可能にし、<optgroup>タグで選択肢を階層化する。
    • CSSの制約
      option要素の描画はOSに依存するため、適用できるCSSは文字色と背景色などに限られる。
    • JSでの値の取得
      ユーザーの操作検知はoptionのクリックではなく、親selectchangeイベントで発火させる。
    • 動的生成とデータ保持
      JSでの選択肢追加にはnew Option()を用い、金額などの付加情報はdata-*属性に保持させる。

    よくある質問(FAQ)

    HTMLの<option>タグとは何ですか?何に使われますか?

    <option>タグは、Webサイトのフォーム等で「プルダウンメニュー(ドロップダウン)」や「リスト」の選択肢を一つひとつ定義するHTMLタグです。

    単体では機能せず、親要素である<select>タグ(または<datalist>タグ)の中に配置して使用します。

    最初から特定の項目を選択された状態にするにはどうすればいいですか?

    画面を開いた時点で特定の項目を選ばれた状態にしておくには、該当する<option>タグにselected属性を追加します。

    (例:<option value="tokyo" selected>東京都</option>)親要素の<select>側にvalue="tokyo"と書いてもHTML標準では機能しないため、子要素の<option>側に記述してください。

    「選択してください」という項目を選べないようにするには?

    一番上のプレースホルダー(案内文)をユーザーが誤って選べないようにするには、<option>タグに対してdisabled属性を追加します。

    実務では「初期表示はさせるが、選べなくしてリストからも隠す」という目的で、<option value="" disabled selected hidden>選択してください</option>のように3つの属性をセットで使うのがベストプラクティスです。

    <option>タグの余白やサイズをCSSで変更することはできますか?

    いいえ、ほとんど変更できません。

    <option>要素の見た目は、OSの標準システムが描画を担当しているため、CSSでpaddingborder-radiusを指定しても基本的に無視されます。

    変更できるのは文字色(color)や背景色などに限られます。

    サイズや余白を変えたい場合は、親要素である<select>タグに対してCSSを適用してください。

    JavaScriptで選択された<option>の値を取得するには?

    ユーザーが項目を選んだ瞬間に値を取得したい場合、<option>タグに直接onclickを書くのはNGです。

    親要素の<select>に対してchangeイベントを監視し、イベントが発火した際にevent.target.valueを読み取ることで、選ばれている<option>value値を取得できます。

    この記事を書いた人

    sugiのアバター sugi Site operator

    【経歴】玉川大学工学部卒業→新卒SIer企業入社→2年半後に独立→プログラミングスクール運営/受託案件→フリーランスエンジニア&SEOコンサル→Python特化のコンテンツサイトJob Code&UIコピペサイトCode Stock運営中

    目次