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