Native <select> repainted with
appearance: none, a chevron caret inlined as an SVG data
URL, and reserved padding on the caret edge. [multiple]
drops the caret and unlocks vertical sizing. The caret position
flips on :dir(rtl) because background-position
has no logical-axis keyword.
One-of-many choices with five or more options. For two to four options, Radio typically wins on scan-ability.
For multi-select short lists, prefer a checkbox group; reserve [multiple] for long lists where a multi-select listbox makes sense.
For typeahead / search-as-you-type, the framework doesn't ship a combobox; lift to a dedicated component.
Variables
Variable
Default
Notes
$selector
'select'
Element selector.
$padding-y
$size-extra-small (0.5rem)
Vertical padding.
$padding-x
$size-small (0.75rem)
Inline-start padding. Also applies to inline-end under [multiple].
$padding-x-with-caret
2rem
Inline-end padding reserved for the caret SVG so option text never collides with it.
$border-radius
$global-border-radius (5px)
Outer corner radius.
$border-width
$global-border-width (1px)
Stroke. Mixed at $border-mix against currentColor.
$focus-outline-width
$global-focus-outline-width (2px)
Focus-visible ring width.
$focus-outline-style
$global-focus-outline-style (solid)
Focus ring style.
$focus-outline-offset
$global-focus-outline-offset (2px)
Gap between border and ring.
$disabled-opacity
$global-disabled-opacity (0.6)
Routed through controls.disabledControl().
$border-mix
$global-border-mix (50%)
Border tint vs. currentColor.
$caret-image
Inline SVG chevron (data URL, stroke #888)
Painted via background-image. Override the SCSS variable to swap the glyph or pin its stroke to a theme token.
Override example
app.scss
@use '@adnap/krysalicss/element/select' with ( $padding-x-with-caret: 2.5rem, $border-radius: 8px,);
Tokens consumed
Token
Used for
--kc-input-bg / --kc-input-fg
Surface fill and text colour. Optional: falls back to transparent + currentColor.
--kc-fg
Focused border colour and focus-ring fallback.
--kc-focus-ring
Painted on :focus-visible. Falls back to --kc-fg then currentColor.
--kc-danger-bg
Border tint when the control matches :user-invalid or [aria-invalid="true"].
Accessibility
Anchored on native <select>: keyboard navigation (Up / Down / type-ahead), AT semantics, and mobile-OS-native pickers ship for free.
Always pair with a <label> (visible or aria-labelledby).
The caret is decorative; option-list state is conveyed by the native widget. The visual cue uses #888 stroke today — adequate against the shipped themes but consumers retuning $caret-image for a custom palette must re-verify WCAG 1.4.11 (3:1).
Focus ring uses --kc-focus-ring with a fallback chain into --kc-fg / currentColor; the focused border also swaps to --kc-fg for redundant non-text contrast.
Under RTL, the caret position flips via the :dir(rtl) companion rule (when $global-rtl: true).
See also
Radio — one-of-many choice when the option count is small (≤ 5) and visibility matters.
Text input — single-line text input with the same chrome.