Skip to content

Select

The same appearance and states as Input, on a real <select>. The browser’s own list is then used, the one that already works with the keyboard, screen readers and the phone’s built-in picker.

data-stateUsed for
(omitted)Normal state
invalidValidation has failed
successThe choice is confirmed valid. Use sparingly.

The first <option> should have an empty value when the field is required. Then required actually stops the submission until the user has chosen something.

The list that pops up is normally a window from the operating system, and no CSS reaches into it. With data-picker="styled" the field asks the browser to draw the list inside the page instead, so it gets the system’s colours, spacing and shadow.

This is the same <select> as before. It is submitted with the form, read by screen readers and works with the keyboard in exactly the same way, and the markup is unchanged apart from the attribute.

An option longer than the field then wraps over several lines, and the field gets taller. If it should be clipped with ”…” instead, put <button><selectedcontent></selectedcontent></button> first in the <select>. The browser does not create <selectedcontent> by itself, but fills it with the selected option when it is there, and LO-TEK clips it. Browsers without support skip the button.

Groups made with <optgroup label="…"> get their heading in smaller, muted text, so it stands apart from the options.

Support differs between browsers, which is why this has to be switched on:

BrowserWhat the user sees
Chromium and Safari that support appearance: base-selectThe list is drawn in the page, with LO-TEK’s colours
FirefoxThe browser’s own list, as without the attribute

That is the one condition the stylesheet asks about, so every version that has appearance: base-select draws the list in the page. LO-TEK is tested in Chromium 148 and WebKit 26.4. Firefox gets no new functionality, but nothing that looks broken either. If all users should see the same thing, leave the attribute out.

In high contrast mode the field falls back to the browser’s own list in all browsers. The system colours are the only ones guaranteed to be readable there.

import { lt } from "@lo-tek/interfaces"
lt.select({ picker: "styled" })
// { class: "lt-select", "data-picker": "styled" }
ClassWhat it is
.lt-selectThe dropdown list. The state comes from data-state, the list from data-picker.
VariableDefaultApplies to
--lt-select-width100%The width of the field
--lt-select-paddingvar(--lt-spacing-2) var(--lt-spacing-3)The space inside the field
--lt-select-radiusvar(--lt-spacing-1)The field, and the list drawn in the page
--lt-select-option-paddingvar(--lt-spacing-2) var(--lt-spacing-3)One option in the list drawn in the page
--lt-select-viewport-marginvar(--lt-spacing-2)Space between the list and the edge of the window

The arrow is two gradients in the background, drawn in --lt-color-neutral-text-subtle, so it follows the theme. To remove it, set background-image: none. With data-picker="styled" the browser draws the arrow itself, and it is styled with ::picker-icon.

In the default appearance the space for the arrow at the end of the field is fixed, since the arrow is drawn a fixed distance from the edge, and --lt-select-padding applies to the other three sides. With data-picker="styled" the arrow takes its own space, and the variable applies to all four.

A compact field, such as “Items per page”, becomes as wide as its content with --lt-select-width: auto. If the label should sit beside the field, the layout around them decides that, not LO-TEK. .lt-label is a block, and a row with display: flex around the two puts them on one line.

See Customising for how the variables and the layer work.

  • An <option> that says “Choose a country” is a label in disguise, not a replacement for <label>.
  • If the list has more than about seven options that belong together logically, group them with <optgroup label="…">.
  • Do not submit the form automatically on change. Keyboard users move through the options with the arrow keys and would submit the form on the first one they pass.
  • If you need search, multiple selection or icons in the list, <select> is the wrong tool. Build it as a standalone component instead of restyling this element.