Slider
المنزلق<input type="range">
also calledrange input، range slider، volume slider، dual range slider، track and thumb، value slider، سلايدر، الشريط المنزلق، شريط الانزلاق، منزلق المدى، مقبض القيمة، شريط تحديد القيمة
A slider is an input for picking one number out of a continuous range, and it expresses that choice as the position of a thumb along a track. The value changes during the drag rather than after it, which suits anything whose effect is visible on the spot: volume, font size, screen brightness, a price ceiling in a search filter. It is not a progress bar: a progress bar is output rather than input, it carries role="progressbar", and no part of it answers to a drag. It is not a scrollbar either, because a scrollbar moves a viewport over content longer than the window and the length of its thumb tells you how much of that content fits on screen, while a slider thumb keeps one size since only its position carries meaning. Nor is it a number field with steppers, which accepts typing and suits exact values the user already knows, whereas a slider trades precision for speed. The rule that settles it in review: if the user knows the number before reaching for the control, give them a field; if they are hunting for it by feel, give them a slider.
If you called it…
Live specimen
Interact with the demo. Every part is real and numbered.
Anatomy: every part, named
Hover a row to locate it in the demo above.
Build prompt
How it behaves right-to-left
This section is ours alone.
The whole axis reverses
mirrorsA horizontal slider is one long inline axis, so all of it turns over in Arabic: the minimum sits at the right, the maximum at the left, and the fill grows leftward. A native <input type="range"> does this on its own because it follows the computed direction of the input element itself, not of the page, and that is where the trap is: any wrapper forcing dir="ltr" around the field (a common habit with numbers and numeric fields) leaves an English-facing slider inside an Arabic page. A custom slider built on left and width knows nothing about direction and comes out of the flip exactly as it went in.
Anchoring the fill and the thumb
mirrorsSwap left: 0; width: 40% for inset-inline-start: 0; inline-size: 40% and the fill mirrors by itself, because the edge it is anchored to is the one that moved. Animating it with transform: scaleX() buys you none of that, since every transform-origin keyword is physical (left, right, top, bottom, center) alongside lengths and percentages, with no logical counterpart anywhere in the property, so the flip costs you a transform-origin: right inside [dir="rtl"] or a direction variable. Centring the thumb is the last trap: inset-inline-start: 40% puts its right edge 40% from the right of the track in RTL, where the usual translateX(-50%) shifts it the wrong way by half its width, so write translateX(calc(-50% * var(--dir))) with --dir set to -1 under [dir="rtl"].
The arrow keys swap meaning
mirrorsThe two horizontal arrows trade places with the axis, so in Arabic ArrowLeft raises the value and ArrowRight lowers it, and a native range input already does this because it reverses the keys along with its rendering. The APG keyboard table for the slider pattern is written from a left to right point of view and never mentions the reversal, which is why hand-written handling like switch (e.key) { case "ArrowRight": v + step } keeps getting copied and keeps handing the Arabic user the opposite of the key pressed. Nothing else on the keyboard moves: ArrowUp raises and ArrowDown lowers in both directions, and Home and End jump to the logical minimum and maximum rather than to the right and left of the screen.
The pointer maths
mirrorsPointer events have no notion of direction: clientX is a physical coordinate, and getBoundingClientRect() reports left and right physically whatever dir says. So the usual (e.clientX - rect.left) / rect.width measures from the physical left edge, which in Arabic is the maximum end, and the value comes out inverted with the thumb jumping to the far side on first touch. Measure from the logical start with (rect.right - e.clientX) / rect.width when getComputedStyle(track).direction === "rtl", and set touch-action: none on the track so page scrolling does not swallow the drag on mobile.
The number itself does not flip
never mirrorsThe axis reverses, the number does not. Digits run left to right inside Arabic text under the bidi algorithm, so never reorder their characters and never flip the label with scaleX(-1). The real problem is the symbols glued to them: a negative value such as -5 renders as 5- inside an Arabic paragraph because the minus resolves to a neutral and takes the paragraph direction, and a Latin unit like km slides to the wrong side of the digits the same way, so isolate every value label in a <bdi> or with unicode-bidi: isolate and generate the text with Intl.NumberFormat so the decimal separator and the currency symbol come out the way the locale expects.
In code
Each row is one framework's word for the same thing. Take the row your project speaks.
See also
Updated · 2026-08-19