Text and choice controls

Select menus

Build a native select control with meaningful option values, an optional prompt, and multiple selection only when the interaction warrants it.

A select shows a fixed list of choices and submits the value of the chosen option.

<label for="country">Country</label>
<select id="country" name="country" required>
  <option value="">Choose a country</option>
  <option value="dk">Denmark</option>
  <option value="it">Italy</option>
</select>

Pick Italy and the request contains country=it. The text inside the option is for people. The value is what the server gets.

If you leave out the value attribute, the browser submits the option’s text instead. So <option>Italy</option> sends country=Italy. That works until someone edits the label, so I always write explicit values.

The empty prompt

The first option has an empty value and acts as a prompt. It tells the person what to do and shows nothing has been chosen yet.

Combined with required, the browser refuses to submit while the prompt is selected. It asks for a real choice first.

Don’t stop there. A handcrafted request can send country= or country=xx. The server must check the value against its own list of countries and reject anything else.

Preselecting an option

To start with a value already chosen, add selected to that option:

<option value="it" selected>Italy</option>

This is how you show a saved value when someone edits their profile.

When a select is the wrong tool

A select is great for a handful of choices. It’s painful for hundreds. Scrolling through 195 countries on a phone is slow, and typing to jump only works in some browsers.

For long lists, an autocomplete or a search field usually works better. Just because the data is a list doesn’t mean the control should be a menu.

Multiple selection

Add multiple only when several choices are allowed:

<select id="topics" name="topic" multiple>
  <option value="html">HTML</option>
  <option value="css">CSS</option>
</select>

Two things change. The control turns into a list box, and selecting several items needs Ctrl or Cmd clicks, which many people don’t know. And the request repeats the name:

topic=html&topic=css

On the server use something like getAll('topic'). Reading only the first value drops the rest.

In practice I reach for a group of checkboxes more often than a multiple select. They’re easier to use and easier to style.

Try this: change the visible country labels without touching their values, then submit again. The request looks exactly the same. That is what a stable contract between the page and the server means.

Lesson completed