Slider
JavaScript off: what the HTML and CSS do on their own.
Usage
@* 0 to 100, the value shown beside it. *@
<Slider @bind-Value="Model!.Volume" ShowValue />
@* Its own ends and steps, read as a percentage. *@
<Slider @bind-Value="Model!.Discount" Min="0" Max="50" Step="5"
ShowValue ValueFormat="{0}%" />It's a native range input, so it posts with the form and moves with the arrow keys, Page Up and Page Down, and Home and End, with or without the script. Use it for a value people judge by eye, such as a volume; when the exact number matters, use a NumberField, or both side by side.
Showing the value
Use ShowValue to show the value beside the slider, and ValueFormat for how it reads, such as "{0}%"; [Range], or Min and Max, set the ends (0 to 100 by default) and Step the increments.
Preview
Code
System.ComponentModel.DataAnnotations
<Form Model="Model" FormName="slider-value" MaxWidth="24.Rem" Grow>
<Slider @bind-Value="Model!.Volume" ShowValue />
<Slider @bind-Value="Model!.Discount" Step="5" ShowValue ValueFormat="{0}%" Hint="In steps of 5, up to 50%." />
</Form>
{
[SupplyParameterFromForm(FormName = "slider-value")]
private Settings? Model { get; set; }
protected override void OnInitialized() => Model ??= new();
public sealed class Settings
{
[Display(Name = "Alert volume")]
public int Volume { get; set; } = 60;
[Range(0, 50), Display(Name = "Launch discount")]
public int Discount { get; set; } = 15;
}
}Off: A plain range input: no fill, and no value beside it.
Saving a value
Bind it like any field: the value posts as a number when the form does.
Preview
Code
System.ComponentModel.DataAnnotations
<Form Model="Model" FormName="slider-budget" OnValidSubmit="Save" MaxWidth="24.Rem" Grow>
<Slider @bind-Value="Model!.Monthly" Step="100" ShowValue ValueFormat="${0}"
Hint="Ads stop for the month once it's spent." />
<Row><Button Submit>Save budget</Button></Row>
if (_saved is { } saved)
{
<Alert Status="Status.Success">Saved: up to $saved a month.</Alert>
}
</Form>
{
[SupplyParameterFromForm(FormName = "slider-budget")]
private Campaign? Model { get; set; }
// What was saved, not the slider: on an interactive page the slider follows each move.
private int? _saved;
protected override void OnInitialized() => Model ??= new();
private void Save() => _saved = Model!.Monthly;
public sealed class Campaign
{
[Range(0, 5000), Display(Name = "Monthly budget")]
public int Monthly { get; set; } = 1200;
}
}Off: Save budget posts the slider's number; the value beside it doesn't follow the thumb.
The browser keeps the value on a step between the ends, so a post from the page is always in range. A crafted post can send any number: the validator checks [Range] on the server, but not the step, so round the value yourself if it must be a multiple.
Following the value live
Use Live on an interactive page to update the bound value as the thumb moves, rather than when it's let go, for something on the page that follows it.
Always Live
Preview
This example runs C# over a Blazor Server connection, which an Off page doesn't have. Show this page Live
Code
System.Globalization
<Form Model="Model" FormName="slider-live" MaxWidth="24.Rem" Grow>
<Slider @bind-Value="Model!.Opacity" Min="0" Max="1" Step="0.05" ShowValue Live />
<Box Bg="Color.Primary" Radius="Radius.Md" Height="3.Rem" Style="($"opacity: {Model!.Opacity.ToString(CultureInfo.InvariantCulture)}")" />
</Form>
{
[SupplyParameterFromForm(FormName = "slider-live")]
private Overlay? Model { get; set; }
protected override void OnInitialized() => Model ??= new();
public sealed class Overlay
{
public double Opacity { get; set; } = 0.8;
}
}Each move is a round trip to the server, so use it only when something follows the value. On a static page the value posts when the form does, either way.
Empty values
A range input always has a value: bound to a nullable type that's null, it shows the thumb at the midpoint (snapped to the step) and posts that value. Use a NumberField when "not set" must stay possible.
Sizes and disabled
Use Size to line up with other fields, and Disabled for a value that can't change, which doesn't post. There's no ReadOnly: HTML has no read-only range input, and in a read-only Form the slider is disabled while a hidden field posts its value.
Preview
Code
System.ComponentModel.DataAnnotations
<Form Model="Model" FormName="slider-states" MaxWidth="24.Rem" Grow>
<Slider @bind-Value="Model!.Small" Label="Small" Size="ControlSize.Sm" />
<Slider @bind-Value="Model!.Large" Label="Large" Size="ControlSize.Lg" />
<Slider @bind-Value="Model!.Backups" Disabled ShowValue Hint="Disabled: not posted." />
</Form>
{
[SupplyParameterFromForm(FormName = "slider-states")]
private Plan? Model { get; set; }
protected override void OnInitialized() => Model ??= new();
public sealed class Plan
{
public int Small { get; set; } = 30;
public int Large { get; set; } = 70;
[Range(0, 30), Display(Name = "Backups kept")]
public int Backups { get; set; } = 7;
}
}Off: Plain range inputs with no values beside them.
A disabled field posts nothing, so after a static post its property holds its default (0, or null): keep its value on the server rather than saving it from the post.
Mode support
| Feature | Off | Static | Live |
|---|---|---|---|
| Drag, arrow keys, Page Up/Down and Home/End; posted with the form | Yes | Yes | Yes |
| The track fills to the thumb, and the shown value follows | No | Yes | Yes |
| Screen readers hear the value as ValueFormat writes it | No | Yes | Yes |
| The bound value follows while dragging (Live) | No | No | Yes |
Off: JavaScript disabled. Static: a static SSR page with IzzyBlazor's script. Live: an interactive page (Server, WebAssembly or Auto).
Accessibility
- It renders a native range
input(a slider to screen readers): arrow keys, Page Up/Down and Home/End move it with no script. - Screen readers hear the value as
ValueFormatwrites it ("20%", througharia-valuetext) once scripts run or on interactive pages; on a static page without script, the bare number. - The value
ShowValueshows is hidden from screen readers, which hear the slider's own value. - Label, hint and errors work as in
TextField.
Parameters
| Prop | Type | Default |
|---|---|---|
MinThe lowest value. | double? | computed |
MaxThe highest value. | double? | computed |
StepThe step between values. | double? | 1 |
ShowValueShows the current value beside the slider. | bool | false |
ValueFormatHow the value reads, with {0} for the number: "{0}%", "${0}". | string | "{0}" |
LiveOn interactive pages, update the bound value while dragging rather than on release. | bool | false |
@bind-ValueThe value, bound with @bind-Value. | TValue | |
DisplayNameThe field's name in validation messages from the input itself, such as a value that can't be parsed. | string? |
Plus 26 field props.
Full APISee also
- NumberField: a number input with stepper buttons.
- SegmentedControl: one choice from a few, as joined buttons.
- Progress: a progress bar, determinate or not.