Introduction
So far in this unit, we've encountered a handful of form controls in HTML. We started with the basic <input>
element, then explored the <textarea>
element, and finally the <button>
element.
We have covered three of the four elements in HTML used to represent form controls. The fourth and last one will be explored in this chapter — <select>
.
The <select>
element is used to represent selection menus in HTML, wherein we have a list of options to choose from. Each option goes in an <option>
element.
There is a host of concepts to learn about selection menus in HTML in this chapter, including what are dropdown menus; how to use <select>
and <option>
; multi-selection <select>
s; grouping options via <optgroup>
; and much more.
So without further ado, let's get learning.
What is the <select>
element?
The <select>
element is used to represent a selection menu in HTML.
<select>
element denotes a selection menu, consisting of a list of options to choose from.In fact, this purpose is evident by the name of the element, that is, <select>
means that we can select from a bunch of choices. Not a bad naming for the element.
Using a selection menu, the user can select either one option or multiple options. In this way, a selection menu is similar to a set of radios when it can accept one single option, or to a set of checkboxes when it can accept multiple options.
By default, <select>
menus are rendered as a text box ending with an arrow (pointing downwards to indicate that a menu will pop up below):
We aren't able to freely enter text into this text box; we can only select from a pre-defined list of options.
When we click on the text box, we see a dropdown menu containing this list of options to choose from. As the name suggests, a dropdown menu is a menu of options that drops down in order to show up, sitting on top of content sort of like a dialog box.
We can select any of these options by clicking on it or by navigating to it using arrow keys and then pressing Enter. The active option typically gets a blue background as can be seen above.
As with all form controls in HTML, the <select>
element can also be given a name that is used when submitting a form containing it. As you probably guess, this name goes in the name
attribute.
name
attribute, refer to HTML Forms — Basics: Control name and value.Besides name
, <select>
can take most of the general attributes of form control elements in HTML, including required
, disabled
, etc.
However, the initial value of a <select>
can NOT go in its value
attribute — as a matter of fact, there is no such attribute as value
on a <select>
! To specify the initial value of a <select>
, we ought to specify the initially selected <option>
(more on that below).
And this takes us to the main point...
On its own, the <select>
element only represents a list of choices; the individual choices themselves are represented using another element — the <option>
element.
The <option>
element
The <option>
element serves to create an option for a <select>
menu.
<option>
is a container element that can contain text for the underlying choice. Keep in mind that <option>
can NOT contain any HTML elements within it; only text.
<option>
can even contain text depends upon the existence of two attributes on it — label
and value
. If both of these are present, <option>
can NOT have any content within it.The following table showcases some common attributes used on <option>
elements:
Attribute | Purpose |
---|---|
selected | Specifies whether the option is pre-selected or not. |
value | The value submitted for the <select> element. |
disabled | Specifies whether the option is disabled or not. |
label | The label, i.e. the text, rendered for the <option> . |
There isn't that much to cover for the <option>
element so let's get straight into some examples in order to understand the working of these few attributes.
Basic examples of <select>
menus
Let's say we want to create a form asking the user to enter his favorite programming language. We previously did a similar thing when demonstrating the usage of radio buttons.
While they are superbly useful when we have a few options to choose from, the thing with radio buttons is that the moment we have many possible choices for a given input, presenting all those choices with radio buttons can become visually overwhelming.
In such a case, we're better off at putting all those choices behind a selection menu.
Coming back to the example, we have a total of 8 choices in this order: C, C#, C++, Perl, PHP, Python, Java, and JavaScript.
The following code creates a <select>
control to represent this set of choices:
<form>
<label>
Your favorite language
<select name="favorite_lang">
<option>C</option>
<option>C#</option>
<option>C++</option>
<option>Perl</option>
<option>PHP</option>
<option>Python</option>
<option>Java</option>
<option>JavaScript</option>
</select>
</label>
<button>Submit</button>
</form>
Let's quickly make sense of what's happening here:
The <select>
is named "favorite_lang"
. This represents the name of the parameter sent in the request the moment we submit the form.
Each option in the <select>
is given by a separate <option>
element, whereby its content represents the text of the choice.
Note that, by default, when <option>
doesn't have value
set, as we have here, its content denotes its value if it gets submitted in the form. So for example if we select the 'JavaScript' option, and then submit the form, the query string of the URL in the address bar would read ?favorite_lang=JavaScript.
And this is all that's there to explain for this elementary example.
Let's add some more bells and whistles to it.
What if we wish to have the 'Java' option pre-selected when the <select>
menu renders? Well, in that case, we ought to set the selected
attribute on the <option>
element corresponding to 'Java'.
This is done as follows:
<form>
<label>
Your favorite language
<select name="favorite_lang">
<option>C</option>
<option>C#</option>
<option>C++</option>
<option>Perl</option>
<option>PHP</option>
<option>Python</option>
<option selected>Java</option>
<option>JavaScript</option>
</select>
</label>
<button>Submit</button>
</form>
Go on and open the link above — you'll notice the <select>
element reading the text 'Java' initially, thanks to the specification of selected
on the <option>
element corresponding to 'Java'.
Great!
Now, typically when websites have <select>
menus containing a large list of options, it's not HTML developers manually coding each and every option; the servers serving these websites instead use the power of given programming languages to dynamically generate these menus.
And in this respect, the options of the menus are already stored somewhere in the server, for e.g. in a database, or as an array in memory, etc.
What's important for us to know is that when this is the case, servers are usually not interested in getting back the exact text of each choice — they already have this knowledge with them. Instead, what servers want is the position of the choice in the list, often referred to as its index in the list. Using the index, they can correctly map to the corresponding text.
Let's take this idea to our example. Clearly, since we're not working with a server-side programming language (like PHP), we'll be indexing each option manually.
Consider the following code:
<form>
<label>
Your favorite language
<select name="favorite_lang">
<option value="0">C</option>
<option value="1">C#</option>
<option value="2">C++</option>
<option value="3">Perl</option>
<option value="4">PHP</option>
<option value="5">Python</option>
<option value="6">Java</option>
<option value="7">JavaScript</option>
</select>
</label>
<button>Submit</button>
</form>
Everything is the same as before, just that each <option>
now has an explicit value
set on it. This value is the index of the option in the list of options.
Now, if we select any option and then submit the form, we'll get something like ?favorite_lang=6 instead of ?favorite_lang=Java.
The server at the back end processing the form will be able to easily determine that the value 6
for the favorite_lang
parameter corresponds to the entry 'Java'.
Grouping options using <optgroup>
When presented with a large list of options, it helps to have them grouped based on their respective categories.
To group multiple <option>
elements together, HTML provides the <optgroup>
element at our dispense. It's a container element, containing all the <option>
elements that fall under the same group.
The label for the group goes as the label
attribute of the <optgroup>
element.
label
but in that case the group's title in the <select>
menu would be displayed as blank space, which doesn't look really nice.For instance, the 8 different programming languages in the <select>
example above can be grouped according to their main paradigm.
For the sake of discussion, C, Perl, and PHP fall under the 'Procedural' paradigm, while C#, C++, Python, Java, and JavaScript fall under the 'Object-oriented' pardigm.
The following figure depicts a <select>
menu having this grouping based on the paradigm:
In the following code, we create a <select>
with this grouping:
<select name="favorite_lang">
<optgroup label="Procedural">
<option>C</option>
<option>Perl</option>
<option>PHP</option>
</optgroup>
<optgroup label="Object-oriented">
<option>C#</option>
<option>C++</option>
<option>Python</option>
<option>Java</option>
<option>JavaScript</option>
</optgroup>
</select>
The first three <option>
elements fall under the same category and hence are nested together inside an <optgroup>
. The same applies to the next five <option>
s — they fall under the same category and hence are nested inside another <optgroup>
.
Both the <optgroup>
elements are labeled, using their label
attributes.
Simple, isn't this?
Using <hr>
s inside <select>
As per the HTML standard's take on the <select>
element, it can contain <optgroup>
, <option>
, <hr>
, and script-supporting (i.e. <script>
) elements only.
Hmm. <hr>
... Let's try using one.
As you may recall, the <hr>
element is used to define a horizontal rule (line) in HTML. It's valid to use it inside a <select>
if we wish to visually further distinguish between two different blocks of options.
Consider the following code where we extend the <optgroup>
example above by placing a rule right after the first group of options:
<select name="favorite_lang">
<optgroup label="Procedural">
<option>C</option>
<option>Perl</option>
<option>PHP</option>
</optgroup>
<hr>
<optgroup label="Object-oriented">
<option>C#</option>
<option>C++</option>
<option>Python</option>
<option>Java</option>
<option>JavaScript</option>
</optgroup>
</select>
Now while <hr>
can be used in <select>
menus, there is not a common usage of it out there, perhaps because it doesn't look that nice when rendered.
So, I'd say to use it sparingly, if at all.
Multi-selection menus using multiple
Without a doubt, the mainstream usage of <select>
is in showcasing dropdown menus where we can select one option from a given list of options. However, HTML allows us to configure <select>
to be able to accept multiple options.
The multiple
attribute comes at play in this respect.
A <select>
element with multiple
set simply means that we can have more than one option selected. It creates what's referred to as a multi-selection menu.
Importantly though, with multiple
, the way a <select>
element is rendered by the browser is quite different from the way it's rendered without multiple
.
That is, a multi-selection menu is not displayed with the currently selected option depicted in a box which, when clicked, shows a dropdown menu of options — there's just no dropdown, so to speak. Instead, we have a normal scrollable box containing all the options in it, at once.
Selecting multiple options in a multi-selection <select>
is a little bit tedious.
If we're using the mouse:
- To select one option, we can simply click on it.
- To select another option (with the previous one still selected), we ought to click on it with the Ctrl key pressed.
If we're using the keyboard:
- To select one option, we can navigate through the options using arrow keys and simply halt the navigation when we arrive at the desired option.
- To select another option (with the previous one still selected), we ought to navigate with the arrow keys, but this time with the Ctrl key pressed. Once we arrive at the desired option, we need to click on the spacebar.
These steps have been simplified to a little extent as we've ignored the interaction of the Shift key in the selections.
All in all, it's not a very trivial thing to select multiple options from a multi-selection <select>
menu. A mere user, who might not know about the fact that Ctrl can often be used to select multiple things (not just in a multi-selection menu but in other kinds of user interfaces) won't be able to use it without frustration.
Anyways, moving on, because a couple of options are shown at once when using a multi-selection menu, the number of these options shown initially is given by the size
attribute of <select>
.
size
gives the display size of a <select>
. When omitted, size
defaults to "0"
but the display size is taken to be 4, i.e. the rendered menu is as big so as to accomodate 4 entries (<option>
and <optgroup>
elements).
size
is omitted, its value is NOT "4"
; it's only the display size for the menu that is 4! Surprising, isn't it?How are multiple selected options in a <select>
submitted?
When we have multiple selections for a <select>
element, they are submitted just like multiple selected checkboxes. That is, each selected <option>
is submitted as its own parameter, with its respective value.
For example, if we have a select named lang
and we select two options with the values "0"
and "1"
, and then submit the form (via the default GET method), the query string will read as follows: ?lang=0&lang=1. lang=0 corresponds to the first selected option and lang=1 corresponds to the second one.
Let's consider a couple of examples to help us better understand all this theory.
In the following code, we transform our familiar favorite language <select>
input into a multi-selection menu by applying the multiple
attribute on it:
<select multiple name="favorite_lang">
<optgroup label="Procedural">
<option>C</option>
<option>Perl</option>
<option>PHP</option>
</optgroup>
<optgroup label="Object-oriented">
<option>C#</option>
<option>C++</option>
<option>Python</option>
<option>Java</option>
<option>JavaScript</option>
</optgroup>
</select>
Note that we've made two additions here in order to make the layout look a little bit better with the multi-selection menu: a <br>
after the label text, to have the <select>
appear below it; and a <br>
after the <select>
, to have the button appear below it as well.
Here's the rendered output for this <select>
:
Notice how we have four entries in the menu; this is because of the default display size of 4 (as the size
attribute is omitted).
Now, let's bring in the size
attribute to increase the display size to 8:
<select multiple size="8" name="favorite_lang">
<optgroup label="Procedural">
<option>C</option>
<option>Perl</option>
<option>PHP</option>
</optgroup>
<optgroup label="Object-oriented">
<option>C#</option>
<option>C++</option>
<option>Python</option>
<option>Java</option>
<option>JavaScript</option>
</optgroup>
</select>
As is evident here, by virtue of size="8"
, we get a total of 8 entries displayed at a time in the multi-selection menu.
size
to a given number, the selection menu will be extended to that very display size. This might mean that, in order to reach that display size, the menu is filled with lots and lots of blank space. Therefore, use size
carefully!Extending this example further, in the following code, we pre-select the first and third languages using the selected
attribute:
<select multiple size="8" name="favorite_lang">
<optgroup label="Procedural">
<option selected>C</option>
<option>Perl</option>
<option selected>PHP</option>
</optgroup>
<optgroup label="Object-oriented">
<option>C#</option>
<option>C++</option>
<option>Python</option>
<option>Java</option>
<option>JavaScript</option>
</optgroup>
</select>