Slider
ui-slider wraps a native <input type="range"> and fills the track up to the thumb. Its value is a number, kept
in sync while the thumb moves. It is form-associated, so the value is submitted under its name, and it keeps the
native range input's keyboard support.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Slider demo</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/dist/theme.css">
<script type="module" src="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.js"></script>
<style>
.demo-narrow {
width: min(100%, calc(var(--spacing) * 88));
}
</style>
</head>
<body>
<import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/slider.html"></import-element>
<div class="demo-narrow">
<ui-slider aria-label="Volume" value="50"></ui-slider>
</div>
</body>
</html>Examples
Range and step
min, max and step work as on the native input.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Slider demo</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/dist/theme.css">
<script type="module" src="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.js"></script>
<style>
.demo-narrow {
width: min(100%, calc(var(--spacing) * 88));
}
.demo-stack {
display: grid;
gap: calc(var(--spacing) * 4);
}
</style>
</head>
<body>
<import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/slider.html"></import-element>
<div class="demo-narrow demo-stack">
<ui-slider aria-label="Opacity" value="0.6" min="0" max="1" step="0.1"></ui-slider>
<ui-slider aria-label="Temperature" value="21" min="16" max="28" step="0.5"></ui-slider>
</div>
</body>
</html>Showing the value
The slider does not print its value. Listen for input to show it while dragging.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Slider demo</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/dist/theme.css">
<script type="module" src="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.js"></script>
</head>
<body>
<import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/label.html"></import-element>
<import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/slider.html"></import-element>
<import-element from="./slider-value-demo.html"></import-element>
<slider-value-demo></slider-value-demo>
</body>
</html><custom-element name="slider-value-demo">
<script>
const brightness = useState({ value: 70 });
function moved(slider) {
brightness.value = slider.value;
}
</script>
<style>
:host {
display: grid;
gap: calc(var(--spacing) * 3);
width: 100%;
max-width: calc(var(--spacing) * 72);
}
.row {
display: flex;
justify-content: space-between;
font-size: var(--text-sm);
}
.value {
color: var(--muted-foreground);
font-variant-numeric: tabular-nums;
}
</style>
<div class="row">
<ui-label for="slider-brightness">Brightness</ui-label>
<span class="value"><slot name="#brightness.value"></slot>%</span>
</div>
<ui-slider id="slider-brightness" value="70" oninput="moved(this)"></ui-slider>
</custom-element>Custom fill colour
The filled part of the track uses --primary. Override the token on an ancestor, for example with a class, to change it.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Slider demo</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/dist/theme.css">
<script type="module" src="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.js"></script>
<style>
.demo-narrow {
width: min(100%, calc(var(--spacing) * 88));
}
</style>
</head>
<body>
<import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/slider.html"></import-element>
<style>
.slider-risk {
--primary: var(--destructive);
}
</style>
<div class="demo-narrow slider-risk">
<ui-slider aria-label="Risk" value="80"></ui-slider>
</div>
</body>
</html>Disabled
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Slider demo</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/dist/theme.css">
<script type="module" src="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.js"></script>
<style>
.demo-narrow {
width: min(100%, calc(var(--spacing) * 88));
}
</style>
</head>
<body>
<import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/slider.html"></import-element>
<div class="demo-narrow">
<ui-slider aria-label="Locked" value="30" disabled></ui-slider>
</div>
</body>
</html>In a form
The value is submitted as a number string under name. Reset returns to the value attribute.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Slider demo</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/dist/theme.css">
<script type="module" src="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.js"></script>
</head>
<body>
<import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/button.html"></import-element>
<import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/slider.html"></import-element>
<import-element from="./slider-form-demo.html"></import-element>
<slider-form-demo></slider-form-demo>
</body>
</html><custom-element name="slider-form-demo">
<script>
const result = useState({ text: "Submit the form to see its data." });
function submit(event) {
event.preventDefault();
result.text = [...new FormData(event.target)].map(([name, value]) => `${name}=${value}`).join("\n");
}
function reset() {
result.text = "The form was reset.";
}
</script>
<style>
:host {
display: grid;
gap: calc(var(--spacing) * 4);
width: 100%;
max-width: calc(var(--spacing) * 80);
}
form {
display: grid;
gap: calc(var(--spacing) * 4);
}
.actions {
display: flex;
gap: calc(var(--spacing) * 2);
}
output {
display: block;
padding: calc(var(--spacing) * 3);
border-radius: var(--radius-md);
background: var(--muted);
font-family: var(--font-mono);
font-size: var(--text-xs);
white-space: pre-wrap;
}
</style>
<form onsubmit="submit(event)" onreset="reset()">
<ui-slider name="budget" aria-label="Budget" value="400" min="0" max="1000" step="50"></ui-slider>
<ui-slider name="quality" aria-label="Quality" value="3" min="1" max="5"></ui-slider>
<div class="actions">
<ui-button type="submit">Apply</ui-button>
<ui-button type="reset" variant="outline">Reset</ui-button>
</div>
</form>
<output><slot name="#result.text"></slot></output>
</custom-element>API
Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
value |
number | 0 |
Current value. The attribute is the initial and reset value. |
min |
number | 0 |
Lowest value. |
max |
number | 100 |
Highest value. |
step |
number | 1 |
Granularity of the value. |
disabled |
boolean | false |
Disables the slider. Also true inside a disabled <fieldset>. |
aria-label |
string | Accessible name, passed to the inner input. Property name: label. |
Properties
| Property | Type | Description |
|---|---|---|
value |
number | Current value as a number. Updated while the thumb moves. Setting it moves the thumb. |
Events
| Event | Detail | Description |
|---|---|---|
input |
none | The inner range input's native input event (composed), fired while dragging. |
change |
none | Dispatched from the element (bubbling) when the user releases the thumb or commits a key press. |
CSS parts
| Part | Description |
|---|---|
control |
The inner native <input type="range">. |
CSS custom properties
| Property | Description |
|---|---|
--state-range-percent |
Set on the host to the filled share of the track, for example 40%. Read-only. Use it to draw a matching tooltip or label. |
Forms
ui-slider is form-associated and submits value under its name. form.reset() restores the value attribute,
and a disabled <fieldset> disables it.
Accessibility
The host delegates focus to the inner native range input, which has the slider role and native keyboard support.
The arrow keys change the value by step, Page Up and Page Down by larger amounts, and Home and End jump to min
and max.