Documentation

Documentation versions (currently viewingVaadin 24)

Select

Select allows users to choose a single value from a list of options presented in an overlay.

Select allows users to choose a single value from a list of options presented in an overlay.

Open in a
new tab
<vaadin-select
  label="Sort by"
  .items="${this.items}"
  .value="${this.items[0].value}"
></vaadin-select>

The drop-down menu can be opened with a click, up and down arrow keys, or by typing the initial character of one of the options.

Dividers

Dividers can be used to group related options. Use dividers sparingly to avoid creating unnecessary visual clutter.

Open in a
new tab
private accessor items = [
  {
    label: 'Most recent first',
    value: 'recent',
  },
  {
    component: 'hr',
  },
  {
    label: 'Rating: high to low',
    value: 'rating-desc',
  },
  {
    label: 'Rating: low to high',
    value: 'rating-asc',
  },
  {
    component: 'hr',
  },
  {
    label: 'Price: high to low',
    value: 'price-desc',
  },
  {
    label: 'Price: low to high',
    value: 'price-asc',
  },
];

For large data sets, it’s preferable to use Combo Box instead of Select. This allows users to filter the list of options.

Disabled Items

Items can be disabled. This prevents users from selecting them, while still showing that the items would be available for selection under different circumstances.

Open in a
new tab
private accessor items = [
  {
    label: 'XS (out of stock)',
    value: 'xs',
    disabled: true,
  },
  {
    label: 'S',
    value: 's',
  },
  {
    label: 'M',
    value: 'm',
  },
  {
    label: 'L',
    value: 'l',
  },
  {
    label: 'XL',
    value: 'xl',
  },
];
Caution
Accessibility
Some assistive technologies might not announce disabled options.

Basic Features

The following features, common to most input field components, are supported:

Label

The label is used to identify the input field. It supports plain-text content, and its length is limited to the width of the field. Helpers and Tooltips can be used to provide additional information that doesn’t fit into the label.

Visible labels are strongly recommended for all input fields. In cases where the built-in label cannot be used, an external element can be associated as the field’s label through the aria-labelledby attribute. Fields without any visible label should include an invisible label for assistive technologies with the aria-label attribute.

Helper

Helpers are used to provide additional information that the user may need to enter in the field, such as format requirements or explanations of the field’s purpose below the field.

A style variant is available for rendering the helper above the field.

In addition to plain text, helpers can contain components and HTML elements. However, complex and interactive content is likely to have accessibility issues.

Tooltip

Tooltips are small text pop-ups displayed on hover, and on keyboard-focus. They can be used to provide additional information about a field. This can be useful in situations where an always visible Helper is not appropriate. Helpers are generally recommended in favor of tooltips, though, as they provide much better discoverability and mobile support. See the Tooltip documentation for more information.

Clear Button

The clear button — which is displayed when the field is not empty — clears the field’s current value. Although the button itself is not keyboard focusable, the clear action can be taken with the Esc key, when the field has focus. The clear button can be especially useful in search and filter fields, where users often need to clear the value. They’re less useful, however, in regular forms.

Prefix

A prefix element — rendered at the start of the field — can be used to display units, icons, and similar visual cues to the field’s purpose or format.

Prefix elements typically don’t work well with assistive technologies like screen readers. Therefore, the information communicated by them should also be conveyed through other means, such as in a Label, a Helper or through ARIA attributes on the field itself.

External & Invisible Labels (ARIA)

Visible labels are strongly recommended for all input fields. In situations where the built-in label cannot be used, an external element can be associated as the field’s label through its element id. Fields without any visible label should be provided an invisible label for assistive technologies like screen readers.

<!-- Associates external element as label: -->
<label id="external-label">This is the label</label>
<vaadin-select accessible-name-ref="external-label">...

<!-- Invisible label for screen readers: -->
<vaadin-select accessible-name="This is the label">...
Open in a
new tab
<vaadin-select
  label="Label"
  helper-text="Helper text"
  placeholder="Placeholder"
  .items="${this.items}"
>
  <vaadin-tooltip slot="tooltip" text="Tooltip text"></vaadin-tooltip>
  <vaadin-icon slot="prefix" icon="vaadin:vaadin-h"></vaadin-icon>
</vaadin-select>

Read-Only & Disabled

Fields used to display values should be set to read-only mode to prevent editing. Read-only fields are focusable and visible to screen readers. They can display tooltips. Their values can be selected and copied.

Fields that are currently unavailable should be disabled. The reduced contrast of disabled fields makes them inappropriate for displaying information. They can’t be focused or display tooltips. They’re invisible to screen readers, and their values cannot be selected and copied.

Disabled fields can be useful in situations where they can become enabled based on some user action. Consider hiding fields entirely if there’s nothing the user can do to make them editable.

Open in a
new tab
<vaadin-select
  readonly
  label="Read-only"
  value="${this.items[0].value}"
  .items="${this.items}"
></vaadin-select>

<vaadin-select disabled label="Disabled"></vaadin-select>

Style Variants

The following style variants can be applied:

Text Alignment

Three different text alignments are supported: left, which is the default; center; and right.

Right-alignment is recommended for numerical values when presented in vertical groups. This tends to aid interpretation and comparison of values.

Small Variant

The small variant can be used to make individual fields more compact. The default size of fields can be customized with style properties.

Helper Above Field

The helper can be rendered above the field, and below the label.

Borders

Borders can be applied to the field surface by providing a value (e.g., 1px) to the --vaadin-input-field-border-width CSS property. This can be applied globally to all input fields using the html selector, or to individual component instances. Borders are required to achieve WCAG 2.1 level AA conformant color contrast with the default Lumo styling of fields.

You can override the default border color with the --vaadin-input-field-border-color property.

Open in a
new tab
<vaadin-select
  theme="align-right small helper-above-field"
  label="Label"
  helper-text="Helper text"
  style="--vaadin-input-field-border-width: 1px;"
  .items="${this.items}"
  value="${this.items[0].value}"
></vaadin-select>

Placeholder

Use the placeholder feature to provide an inline text prompt for the field. Don’t create or use a separate item for this purpose.

Open in a
new tab
<vaadin-select label="Size" placeholder="Select size" .items="${this.items}"></vaadin-select>

Empty Selection Item (Flow Only)

An empty item can be set as the first option. Use it in cases where you want to allow users to clear their selection. The value of the empty item is represented as null.

Open in a
new tab
select.setEmptySelectionAllowed(true);

Customizing Empty Selection Caption

The label for the empty item is customizable. The caption that you set replaces the placeholder for the empty selection item.

Open in a
new tab
select.setEmptySelectionAllowed(true);
select.setEmptySelectionCaption("Unknown size");

Custom Item Label

When using complex values, a label can be set to represent the item value as plain text.

Open in a
new tab
this.items = people.map((person) => ({
  label: `${person.firstName} ${person.lastName}`,
  value: `${person.id}`,
}));

When using custom item renderers with rich content, a label can be set to represent the item value when it’s selected.

Open in a
new tab
<!-- Use the label attribute to display full name of the person as selected value label -->
<vaadin-item value="${person.id}" label="${formatPersonFullName(person)}">
  <div style="display: flex; align-items: center;">
    <img
      src="${person.pictureUrl}"
      alt="Portrait of ${formatPersonFullName(person)}"
      style="width: var(--lumo-size-m); margin-right: var(--lumo-space-s);"
    />
    <div>
      ${formatPersonFullName(person)}
      <div
        style="font-size: var(--lumo-font-size-s); color: var(--lumo-secondary-text-color);"
      >
        ${person.profession}
      </div>
    </div>
  </div>
</vaadin-item>
Note
Flow-Specific

When using setItemLabelGenerator() in combination with setEmptySelectionAllowed(), ensure that the implementation is capable of handling null values, as the empty selection item has the value null.

select.setEmptySelectionAllowed(true);
select.setItemLabelGenerator(person -> {
  if (person == null) {
      return "No assignee";
  }
  return person.getFullName();
});

The same applies when using a data source that may contain null values.

Custom Item Presentation

Items can be rendered with rich content instead of plain text. This can be useful to provide information in a more legible fashion than appending it to the item text.

Open in a
new tab
<vaadin-select
  label="Choose doctor"
  ${selectRenderer(this.renderer, this.people)}
></vaadin-select>

...

private renderer = () => html`
  <vaadin-list-box>
    ${this.people.map(
      (person) => html`
        <vaadin-item value="${person.id}">
          <!--
          NOTE
          We are using inline styles here to keep the example simple.
          We recommend placing CSS in a separate style sheet and
          encapsulating the styling in a new component.
        -->
          <div style="display: flex; align-items: center;">
            <img
              src="${person.pictureUrl}"
              alt="Portrait of ${person.firstName} ${person.lastName}"
              style="width: var(--lumo-size-m); margin-right: var(--lumo-space-s);"
            />
            <div>
              ${person.firstName} ${person.lastName}
              <div
                style="font-size: var(--lumo-font-size-s); color: var(--lumo-secondary-text-color);"
              >
                ${person.profession}
              </div>
            </div>
          </div>
        </vaadin-item>
      `
    )}
  </vaadin-list-box>
`;

Best Practices

Set a Default Value

Where applicable, set the most common choice as the default value.

Don’t Use as a Menu

Select is an input field component, not a generic menu component. Use Menu Bar to create overlays for actions.

Component Usage Recommendation

Radio Button

Better accessibility than Select, as all options are visible without user interaction.

Combo Box

Filterable list of options. Appropriate for large sets of options. Supports lazy-loading entry of custom values.

List Box

Scrollable inline list of options. Supports single and multi-select.

Menu Bar

Overlay menus for items that trigger actions.

F53C23C7-4798-402A-A7C9-47416795D4C5