jQuery / Selector / :selected — Select the chosen options in a select

jQuery :selected matches the currently selected option elements inside a select. $("#fruit option:selected") retrieves the options; $("#fruit").val() reads the value directly. The selected HTML attribute and the user’s current selection can differ.

Elements, values, and labels

The :selected reference applies to options, not checkbox or radio inputs. Scope the query to a particular select or form so other controls do not contaminate the result.

An option’s .text() is its label; .val() is its value. Calling .val() on a collection of several options returns only the first value, while .text() concatenates all their text. For all values of a multiple select, read .val() on the select itself. For element-specific information, map or iterate the options.

The example separates one fruit from several topics, using JavaScript as a label and js as an identifier. Disabled options and a disabled optgroup expose the difference between selected state and eligible submitted values.

Complete single and multiple example

Save UTF-8 as selected-demo.html and open it. Internet loads full jQuery 4.0.0, without a server or build. Windows Edge tests with 4.0.0 and 3.7.1 covered initial state, keyboard changes, disabled options, empty selection, and reset.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Read selected options and submitted values</title>
  <script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
  <style>
    body { font: 16px/1.6 sans-serif; max-width: 740px; margin: 20px; }
    label { display: block; margin-top: 12px; }
    select, button { font: inherit; max-width: 100%; margin: 6px 0; }
    #topics { display: block; min-width: 230px; }
    pre { white-space: pre-wrap; overflow-wrap: anywhere; }
  </style>
</head>
<body>
  <form id="chooser">
    <label for="fruit">Fruit (single)</label>
    <select id="fruit" name="fruit"><option value="apple">Apple</option><option value="banana">Banana</option></select>
    <label for="topics">Topics (multiple)</label>
    <select id="topics" name="topics" multiple size="6">
      <option value="js" selected>JavaScript</option>
      <option value="css">CSS</option>
      <option value="html" selected disabled>HTML (disabled)</option>
      <optgroup label="Unavailable group" disabled><option value="legacy" selected>Legacy</option></optgroup>
    </select>
    <button type="button" id="set">Set Banana and CSS</button>
    <button type="button" id="clear">Clear topics</button>
    <button type="button" id="restore">Reset</button>
  </form>
  <pre id="result" aria-live="polite"></pre>
  <script>
    jQuery(function ($) {
      const $fruit = $("#fruit"), $topics = $("#topics"), form = document.querySelector("#chooser");
      let changes = 0;
      function values($options) { return $options.map(function () { return this.value; }).get(); }
      function render() {
        const $selected = $topics.find("option").filter(":selected");
        const data = new URLSearchParams(new FormData(form));
        $("#result").text("single=" + $fruit.val() + "\nsingleText=" + $fruit.find("option:selected").text() +
          "\nselectedOptions=" + JSON.stringify(values($selected)) + "\nvalues=" + JSON.stringify($topics.val()) +
          "\nselectedAttribute=" + JSON.stringify(values($topics.find("option[selected]"))) +
          "\nform=" + data.toString() + "\nchanges=" + changes);
      }
      $fruit.add($topics).on("change", function () { changes++; render(); });
      $("#set").on("click", function () {
        $fruit.val("banana").trigger("change"); $topics.val(["css"]).trigger("change");
      });
      $("#clear").on("click", function () { $topics.val([]).trigger("change"); });
      $("#restore").on("click", function () { form.reset(); changes = 0; render(); });
      render();
    });
  </script>
</body>
</html>

Initially Fruit has no selected attribute, but Apple is selected as the single select’s first item. Three topics have selected state, yet only js is eligible for submission.

single=apple
singleText=Apple
selectedOptions=["js","html","legacy"]
values=["js"]
selectedAttribute=["js","html","legacy"]
form=fruit=apple&topics=js
changes=0
  1. Choose Banana. single=banana and singleText=Banana update together, including through keyboard changes.
  2. Set Banana and CSS makes selectedOptions and values ["css"], while selectedAttribute stays ["js","html","legacy"].
  3. Clear topics makes selectedOptions and values empty arrays. Form data contains fruit without topics.
  4. Reset restores the original state, including disabled HTML and Legacy selections.
  5. Manual multiple selection uses the operating system’s and browser’s selection keys. Buttons provide consistent comparison conditions across devices.

selectedOptions lists selected DOM values, values is the select’s .val(), and selectedAttribute lists attributes still present. form is a URL-query representation of FormData, not a server request. changes counts change handling; the Set button emits one event for each select, hence two.

Current state versus default attribute

option.selected and :selected describe current state. [selected] tests attribute presence, while defaultSelected represents the default. User changes do not rewrite that default in the same way. Do not use [selected] to inspect current choices.

.val(["css"]) changes current selection and .val([]) clears multiple selection. The .val() setter does not emit change automatically, so the example triggers it to refresh output. Without an event or render call, a report can remain stale even though the control changed.

In jQuery 3+, an unselected multiple select returns []. An empty option collection’s .val() is undefined. A single select with no selection after an unknown value is set returns null. These are not all empty strings.

Reset calls form.reset() then render. Editing default attributes would change the reset destination. This exercise preserves attributes and changes current values only, making its initial comparison reproducible.

Disabled state, :checked, and integration

Disabled options, including those under disabled optgroups, can remain selected but are omitted from select .val() and FormData. A selected-option count is not a submitted-value count. That is why three selected DOM options initially yield one value. Also consider missing name or a disabled select when constructing real form data.

:checked matches selected options as well as checkboxes and radios. A scoped option:checked gives the same options here, while a global :checked can mix control types.

:selected is a jQuery extension and cannot be passed directly to native document.querySelectorAll(). The example selects options with CSS then filters :selected. Native code may use select.selectedOptions or a scoped option:checked.

When applying a selection to colors or filters, render once at initialization as well as on changes. Define a refresh path for scripted assignments. Display labels with .text() rather than concatenated HTML, and validate submitted identifiers and business rules again on the server.