KTUIKTUI
KTUIKTUI
ComponentsDocsStudio

Getting Started

IntroductionInstallationApproachThemingJavaScriptTypeScriptDark modeRTLReferencesChangelog - v1.2.5Metronic TemplatePopular

Components

AccordionAvatarAlertBadgeBreadcrumbButtonCardCarouselNewClipboardNewCheckboxCollapseDatatableUpdateContext MenuNewDismissDrawerDropdownImage InputInputInput numberNewKbdLinkModalPaginationPin inputNewProgressRadio GroupRange SliderNewRatingNewReparentRepeaterNewScrollableScrollspyScrolltoSelectSeparatorSkeletonStepperStickySwitchTabsTextareaTheme SwitchToastTooltipToggleToggle GroupToggle PasswordTooltip
©2026 KtUI. All rights reserved.
A project by Keenthemes
Docs
Range Slider

Range Slider

Single-thumb range control built on the native input[type=range] with KtUI lifecycle, optional value output, and a CSS variable for track fill.

Examples

Basic

Initialize on a wrapper that contains one input[type="range"]. The component stores --kt-range-fill on the root (0–1) so you can drive a visual track or theme styles.

<div class="w-full max-w-md space-y-3" data-kt-range-slider="true">
  <input
    type="range"
    class="w-full accent-primary"
    min="0"
    max="100"
    value="40"
  />
</div>

With output

Point data-kt-range-slider-output at a selector for an element whose text updates on input and change (searched under the root first, then document).

<div
  class="w-full max-w-md space-y-3"
  data-kt-range-slider="true"
  data-kt-range-slider-output="#kt-range-slider-value"
>
  <div class="flex items-center justify-between gap-3 text-sm">
    <span class="text-muted-foreground">Level</span
    ><span id="kt-range-slider-value" class="tabular-nums font-medium">25</span>
  </div>
  <input
    type="range"
    class="w-full accent-primary"
    min="0"
    max="100"
    value="25"
  />
</div>

Disabled

Use the native disabled attribute on the range input. The control stays a real form field; avoid replacing it with a non-focusable custom thumb.

<div class="w-full max-w-md space-y-3 opacity-80" data-kt-range-slider="true">
  <input
    type="range"
    class="w-full accent-primary"
    min="0"
    max="100"
    disabled=""
    value="60"
  />
  <p class="text-xs text-muted-foreground">
    Native <code class="text-foreground/80">disabled</code> — no pointer events;
    keyboard focus depends on the browser.
  </p>
</div>

Stepped bounds

Define explicit min, max, and step values to constrain user input to predictable increments.

<div
  class="w-full max-w-md space-y-3"
  data-kt-range-slider="true"
  data-kt-range-slider-output="#kt-range-slider-stepped-value"
>
  <div class="flex items-center justify-between gap-3 text-sm">
    <span class="text-muted-foreground">Value</span
    ><span id="kt-range-slider-stepped-value" class="font-medium tabular-nums"
      >35</span
    >
  </div>
  <input
    type="range"
    class="w-full accent-primary"
    min="10"
    max="90"
    step="5"
    value="35"
  />
  <p class="text-xs text-muted-foreground">
    Uses native bounds with
    <code class="text-foreground/80">min=10</code>,<!-- -->
    <code class="text-foreground/80">max=90</code>, and<!-- -->
    <code class="text-foreground/80">step=5</code>.
  </p>
</div>

Datalist ticks

Use native list and <datalist> to add browser-supported tick references for common values.

<div
  class="w-full max-w-md space-y-3"
  data-kt-range-slider="true"
  data-kt-range-slider-output="#kt-range-slider-ticks-value"
>
  <div class="flex items-center justify-between gap-3 text-sm">
    <span class="text-muted-foreground">Value</span
    ><span id="kt-range-slider-ticks-value" class="font-medium tabular-nums"
      >50</span
    >
  </div>
  <div
    class="flex items-center justify-between gap-3 text-xs text-muted-foreground"
  >
    <span>0</span><span>25</span><span>50</span><span>75</span><span>100</span>
  </div>
  <input
    type="range"
    class="w-full accent-primary"
    min="0"
    max="100"
    step="5"
    list="kt-range-slider-ticks"
    value="50"
  /><datalist id="kt-range-slider-ticks">
    <option value="0"></option>
    <option value="25"></option>
    <option value="50"></option>
    <option value="75"></option>
    <option value="100"></option>
  </datalist>
  <p class="text-xs text-muted-foreground">
    Native tick marks via <code class="text-foreground/80">list</code> +<!-- -->
    <code class="text-foreground/80">&lt;datalist&gt;</code>.
  </p>
</div>

Form integration

Keep the range input in a standard form so submission and readout work with native semantics.

<div class="w-full max-w-md space-y-4">
  <form id="kt-range-slider-form" class="space-y-3">
    <div
      class="space-y-2"
      data-kt-range-slider="true"
      data-kt-range-slider-output="#kt-range-slider-form-output"
    >
      <div class="flex items-center justify-between gap-3 text-sm">
        <label for="kt-range-slider-form-value" class="text-muted-foreground"
          >Satisfaction</label
        ><span id="kt-range-slider-form-output" class="font-medium tabular-nums"
          >70</span
        >
      </div>
      <input
        id="kt-range-slider-form-value"
        type="range"
        class="w-full accent-primary"
        min="0"
        max="100"
        name="satisfaction"
        value="70"
      />
    </div>
    <button type="submit" class="kt-btn kt-btn-sm kt-btn-primary">
      Submit
    </button>
  </form>
  <p id="kt-range-slider-form-readout" class="text-xs text-muted-foreground">
    Submit to read native form data.
  </p>
  <script>
    (function () {
      var form = document.getElementById("kt-range-slider-form");
      var readout = document.getElementById("kt-range-slider-form-readout");
      if (!form || !readout) return;

      form.addEventListener("submit", function (event) {
        event.preventDefault();
        var formData = new FormData(form);
        var value = formData.get("satisfaction");
        readout.textContent = "Submitted value: " + String(value ?? "");
      });
    })();
  </script>
</div>

Programmatic update

Use external controls to set preset values while keeping slider output in sync.

<div
  class="w-full max-w-md space-y-3"
  data-kt-range-slider="true"
  data-kt-range-slider-output="#kt-range-slider-programmatic-value"
>
  <div class="flex items-center justify-between gap-3 text-sm">
    <span class="text-muted-foreground">Progress</span
    ><span
      id="kt-range-slider-programmatic-value"
      class="font-medium tabular-nums"
      >50</span
    >
  </div>
  <input
    id="kt-range-slider-programmatic-input"
    type="range"
    class="w-full accent-primary"
    min="0"
    max="100"
    value="50"
  />
  <div class="flex flex-wrap gap-2">
    <button
      type="button"
      class="kt-btn kt-btn-sm kt-btn-outline"
      data-set-range="25"
    >
      Set 25%</button
    ><button
      type="button"
      class="kt-btn kt-btn-sm kt-btn-outline"
      data-set-range="50"
    >
      Set 50%</button
    ><button
      type="button"
      class="kt-btn kt-btn-sm kt-btn-outline"
      data-set-range="75"
    >
      Set 75%
    </button>
  </div>
  <script>
    (function () {
      var input = document.getElementById("kt-range-slider-programmatic-input");
      if (!input) return;

      var buttons = document.querySelectorAll("[data-set-range]");
      buttons.forEach(function (button) {
        button.addEventListener("click", function () {
          var next = button.getAttribute("data-set-range");
          if (!next) return;
          input.value = next;
          input.dispatchEvent(new Event("input", { bubbles: true }));
          input.dispatchEvent(new Event("change", { bubbles: true }));
        });
      });
    })();
  </script>
</div>

Usage

Wrapper root

<div data-kt-range-slider>
  <input type="range" min="0" max="100" value="40" />
</div>

Input root

You may also put data-kt-range-slider directly on the range input. getElement() returns that input.

<input type="range" min="0" max="100" value="40" data-kt-range-slider />

If a wrapper contains more than one range input, the component binds to the first in tree order (avoid duplicate controls in one instance).

Component API

Options

NameTypeDefaultDescription
data-kt-range-sliderflag—Enables auto-init on the element.
data-kt-range-slider-outputstring

min, max, step, and value use the native attributes on input[type="range"].

Track fill (CSS)

Custom propertyWhereDescription
--kt-range-fillRoot element passed to the instanceNumber from 0 to 1: (value - min) / (max - min). Updated on each input.

Example (Tailwind-friendly): style={{ width: 'calc(var(--kt-range-fill, 0) * 100%)' }} on an inner bar.

Methods

MethodDescription
new KTRangeSlider(element, options?)Creates an instance if markup includes a range input.
getRangeInput()Returns the controlled HTMLInputElement or null.
getValue()Current numeric value from the input.

Static methods

MethodDescription
KTRangeSlider.init()Initializes [data-kt-range-slider] (except lazy).
KTRangeSlider.createInstances()Same discovery; safe to call after DOM updates.
KTRangeSlider.getInstance(element)Returns the instance on the root, or null.
KTRangeSlider.init();
 
const el = document.querySelector('[data-kt-range-slider]');
const slider = KTRangeSlider.getInstance(el);
console.log(slider?.getValue());

Events

Native input and change on the range control still fire. KtUI dispatches:

EventWhenevent.detail.payload
kt.range-slider.inputNative input{ value, min, max } (numbers), plus step when the input has a numeric step (omitted for step="any")
kt.range-slider.changeNative
root.addEventListener('kt.range-slider.input', (e) => {
  console.log(e.detail.payload.value);
});

Accessibility

Focus, keyboard arrows, and screen reader behavior come from the native input[type="range"]. Keep the native input in the tab order and visible.

TypeScript

import {
  KTRangeSlider,
  type KTRangeSliderConfigInterface,
  type KTRangeSliderInterface,
  type KTRangeSliderEventPayloadInterface,
} from '@keenthemes/ktui';
 
const root = document.querySelector<HTMLElement>('[data-kt-range-slider]');
if (!root) {
  throw new Error('missing root');
}
 
const slider: KTRangeSliderInterface | null =
  KTRangeSlider.getOrCreateInstance(root, {
    output: '#kt-range-slider-value',
  } satisfies KTRangeSliderConfigInterface);
 
if








PreviouseRadio GroupNextRating

On This Page

  • Examples
    • Basic
    • With output
    • Disabled
    • Stepped bounds
    • Datalist ticks
    • Form integration
    • Programmatic update
  • Usage
    • Wrapper root
    • Input root
  • Component API
    • Options
    • Track fill (CSS)
    • Methods
    • Static methods
    • Events
  • Accessibility
  • TypeScript
—
CSS selector for a value label; text updates with the input value.
data-kt-range-slider-lazybooleanfalseSkip auto-init; create with getOrCreateInstance or new KTRangeSlider(...).
getOption(name)Option from merged config / data attributes.
getElement()Root element (wrapper or the input).
on / offInstance callback map (see Events).
dispose()Removes listeners and clears the instance from KTData.
KTRangeSlider.getOrCreateInstance(element, config?)Returns an instance or null if no range input exists.
change
Same shape as input
(slider) {
const input = slider.getRangeInput();
const detail: KTRangeSliderEventPayloadInterface = {
value: slider.getValue(),
min: input ? parseFloat(input.min || '0') : 0,
max: input ? parseFloat(input.max || '100') : 100,
};
// Event payloads from `kt.range-slider.*` also include `step` when the input has a numeric step.
console.log(detail);
}