Range Slider

Range Slider Layout

Single Range

Single range slider layout is pretty simple:

<!-- Range Slider element -->
<div class="range-slider">
  <!-- range input -->
  <input type="range" min="0" max="100" step="1" value="10" />
</div>

Dual Range

Dual range slider is more simpler as it doesn't require input element because input:range doesn't support dual range:

<!-- Range Slider element -->
<div class="range-slider"></div>

Range Slider Colors

Range Slider supports all default colors. So to change its color just add color-[color] class to range slider element.

<!-- red range -->
<div class="range-slider color-red">...</div>

<!-- orange range -->
<div class="range-slider color-orange">...</div>

Range Slider App Methods

Let's look at related App methods to work with Range Slider:

app.range.create(parameters)- create Range Slider instance

  • parameters - object. Object with range slider parameters

Method returns created Range Slider's instance

app.range.destroy(el)- destroy Range Slider instance

  • el - HTMLElement or string (with CSS Selector) or object. Range Slider element or Range Slider instance to destroy.

app.range.get(el)- get Range Slider instance by HTML element

  • el - HTMLElement or string (with CSS Selector). Range Slider element.

Method returns Range Slider's instance

app.range.getValue(el)- get Range Slider value

  • el - HTMLElement or string (with CSS Selector). Range Slider element.

Method returns range slider value

app.range.setValue(el, value)- set new Range Slider value

  • el - HTMLElement or string (with CSS Selector). Range Slider element.
  • value - number (in case of single range) or array of values (in case of dual range)

Method returns Range Slider's instance

Range Slider Parameters

Now let's look at list of available parameters we need to create Range Slider:

ParameterTypeDefaultDescription
elHTMLElement
string
Range Slider element. HTMLElement or string with CSS selector of range slider element
inputElHTMLElement
string
Range Slider input element or CSS selector of input element. If not specified, will try to look for input type="range" inside of range slider element
dualbooleanfalseEnable dual range slider
stepnumber1Minimal step between values
labelbooleanfalseEnables additional label around range slider knob
formatLabelfunction(value)Method must return formatted range knob label text. As an argument it receives label value
minnumberMinimum value
maxnumberMaximum value
valuenumber
array
Initial value. Number in case of single range, and array of values in case of dual range
draggableBarbooleantrueWhen enabled it is also possible to interact with range slider (change value) on range bar click and swipe.
verticalbooleanfalseEnables vertical range slider
verticalReversedbooleanfalseMakes vertical range slider reversed (vertical must be also enabled)
scalebooleanfalseEnables range slider scale
scaleStepsnumber5Number of scale steps
scaleSubStepsnumber0Number of scale sub steps (each step will be divided by this value)
formatScaleLabelfunction (value)Method must return formatted scale value. As an argument it receives currect scale step value. This method will be called as for each scale step.
limitKnobPositionbooleanLimits knob position to the size of the range bar. By default enabled from iOS theme
onobject

Object with events handlers. For example:

var range = app.range.create({
  el: '.range-slider',
  on: {
    change: function () {
      console.log('Range Slider value changed')
    }
  }
})

Range Slider Methods & Properties

So to create Range Slider we have to call:

var range = app.range.create({ /* parameters */ })

After that we have its initialized instance (like range variable in example above) with useful methods and properties:

Properties
range.appLink to global app instance
range.elRange Slider HTML element
range.$elDom7 instance with range slider HTML element
range.inputElRange Slider input HTML element
range.$inputElDom7 instance with range slider input HTML element
range.rangeWidthRange slider width (in px)
range.dualBoolean property indicating whether it is dual or not
range.minRange min value
range.maxRange max value
range.valueRange value
range.scaleBoolean property indicating whether scale is enabled or not
range.scaleStepsNumber of scale steps
range.scaleSubStepsNumber of scale sub steps
range.$scaleElDom7 instance with generated scale HTML element
range.knobsArray where each element represents HTMLElement of created range knob (2 knobs in case of dual slider)
range.labelsArray where each element represent HTMLElement of created range knob label (2 labels in case of dual slider)
range.verticalBoolean property indicating whether it is vertical or not
range.verticalReversedBoolean property indicating whether it is vertical and reversed or not
range.paramsRange Slider parameters
Methods
range.getValue()Returns range slider value
range.setValue(value)Set new range slider value
range.updateScale()Re-calculate and re-render slider scale
range.destroy()Destroys range slider instance
range.on(event, handler)Add event handler
range.once(event, handler)Add event handler that will be removed after it was fired
range.off(event, handler)Remove event handler
range.off(event)Remove all handlers for specified event
range.emit(event, ...args)Fire event on instance

Range Slider Events

Range Slider will fire the following DOM events on range element and events on app and range instance:

DOM Events

EventTargetDescription
range:changeRange Slider Element<div class="range-slider">Event will be triggered when Range Slider value has been changed
range:changedRange Slider Element<div class="range-slider">Event will be triggered on slider knob release after value change
range:beforedestroyRange Slider Element<div class="range-slider">Event will be triggered right before Range Slider instance will be destroyed

App and Range Slider Instance Events

Range Slider instance emits events on both self instance and app instance. App instance events has same names prefixed with range.

EventArgumentsTargetDescription
change(range, value)rangeEvent will be triggered when range value has been changed. As an argument event handler receives range instance
rangeChange(range, value)app
changed(range, value)rangeEvent will be triggered on slider knob release after value change. As an argument event handler receives range instance
rangeChanged(range, value)app
beforeDestroy(range)rangeEvent will be triggered right before Range Slider instance will be destroyed. As an argument event handler receives range instance
rangeBeforeDestroy(range)app

Range Slider Auto Initialization

If you don't need to use Range Slider API and your Range Slider is inside of the page and presented in DOM on moment of page initialization then it can be auto initialized with just adding additional range-slider-init class:

<!-- Add range-slider-init class -->
<div class="range-slider range-slider-init">
  <input type="range" min="0" max="100" step="1" value="10" />
</div>

In this case if you need to access created Range Slider instance you can use the app.range.get app method:

var range = app.range.get('.range-slider');

if (range.value > 50) {
  // do something
}

When using auto init you may need to pass additional parameters. It can be done with two ways:

CSS Variables

Below is the list of related CSS variables (CSS custom properties).

Note that commented variables are not specified by default and their values is what they fallback to in this case.

:root {
  /*
  --f7-range-bar-active-bg-color: var(--f7-theme-color);
  --f7-range-scale-bg-color: var(--f7-range-bar-bg-color);
  --f7-range-scale-substep-bg-color: var(--f7-range-bar-bg-color);
  */
  --f7-range-scale-step-height: 5px;
  --f7-range-scale-substep-width: 1px;
  --f7-range-scale-substep-height: 4px;
  --f7-range-bar-bg-color: rgba(0, 0, 0, 0.2);
}
:root .dark,
:root.dark {
  --f7-range-bar-bg-color: rgba(255, 255, 255, 0.2);
}
.ios {
  --f7-range-size: 28px;
  --f7-range-bar-size: 4px;
  --f7-range-bar-border-radius: 2px;
  --f7-range-knob-size: 28px;
  --f7-range-knob-color: #fff;
  --f7-range-knob-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
  --f7-range-label-size: 24px;
  --f7-range-label-text-color: #000;
  --f7-range-label-bg-color: #fff;
  --f7-range-label-font-size: 12px;
  --f7-range-label-font-weight: 500;
  --f7-range-label-border-radius: 5px;
  --f7-range-label-padding: 0px 2px;
  --f7-range-scale-text-color: #666;
  --f7-range-scale-step-width: 1px;
  --f7-range-scale-font-size: 12px;
  --f7-range-scale-font-weight: 400;
  --f7-range-scale-label-offset: 4px;
}
.md {
  --f7-range-size: 20px;
  --f7-range-bar-size: 2px;
  --f7-range-bar-border-radius: 0px;
  --f7-range-knob-size: 12px;
  --f7-range-knob-box-shadow: none;
  --f7-range-label-size: 26px;
  --f7-range-label-font-weight: normal;
  --f7-range-label-font-size: 10px;
  --f7-range-label-border-radius: 50%;
  --f7-range-label-padding: 0px;
  --f7-range-scale-step-width: 2px;
  --f7-range-scale-font-size: 12px;
  --f7-range-scale-font-weight: 400;
  --f7-range-scale-label-offset: 4px;
}
.md,
.md .dark,
.md [class*='color-'] {
  --f7-range-knob-color: var(--f7-theme-color);
  --f7-range-label-text-color: var(--f7-md-on-primary);
  --f7-range-label-bg-color: var(--f7-theme-color);
  --f7-range-scale-text-color: var(--f7-md-on-surface-variant);
}

Examples

range.html
<template>
  <div class="page">
    <div class="navbar">
      <div class="navbar-bg"></div>
      <div class="navbar-inner sliding">
        <div class="title">Range Slider</div>
      </div>
    </div>
    <div class="page-content">
      <div class="block-title">Volume</div>
      <div class="list list-strong-ios list-outline-ios simple-list">
        <ul>
          <li>
            <div>
              <i class="icon f7-icons if-not-md" style="width: 28px">speaker_fill</i>
              <i class="icon material-icons md-only" style="width: 24px">volume_mute</i>
            </div>
            <div style="width: 100%; margin: 0 16px">
              <div class="range-slider range-slider-init">
                <input type="range" min="0" max="100" step="1" value="10" />
              </div>
            </div>
            <div>
              <i class="icon f7-icons if-not-md" style="width: 28px">speaker_3_fill</i>
              <i class="icon material-icons md-only" style="width: 24px">volume_up</i>
            </div>
          </li>
        </ul>
      </div>
      <div class="block-title">Brightness</div>
      <div class="list list-strong-ios list-outline-ios simple-list">
        <ul>
          <li>
            <div>
              <i class="icon f7-icons if-not-md" style="width: 28px">sun_min</i>
              <i class="icon material-icons md-only" style="width: 24px">brightness_low</i>
            </div>
            <div style="width: 100%; margin: 0 16px">
              <div class="range-slider range-slider-init color-orange" data-label="true">
                <input type="range" min="0" max="100" step="1" value="50" />
              </div>
            </div>
            <div>
              <i class="icon f7-icons if-not-md" style="width: 28px">sun_max_fill</i>
              <i class="icon material-icons md-only" style="width: 24px">brightness_high</i>
            </div>
          </li>
        </ul>
      </div>
      <div class="block-title display-flex justify-content-space-between">
        Price Filter <span class="price-value">$${priceMin} - $${priceMax}</span>
      </div>
      <div class="list list-strong-ios list-outline-ios simple-list">
        <ul>
          <li class="item-row">
            <div>
              <i class="icon f7-icons if-not-md" style="width: 28px">money_dollar_circle</i>
              <i class="icon material-icons md-only" style="width: 24px">attach_money</i>
            </div>
            <div style="width: 100%; margin: 0 16px">
              <div class="range-slider range-slider-init color-green" @range:change=${onPriceChange} data-label="true"
                data-dual="true" data-min="0" data-max="500" data-step="1" data-value-left="200" data-value-right="400">
              </div>
            </div>
            <div>
              <i class="icon f7-icons if-not-md" style="width: 28px">money_dollar_circle_fill</i>
              <i class="icon material-icons md-only" style="width: 24px">monetization_on</i>
            </div>
          </li>
        </ul>
      </div>
      <div class="block-title">With Scale</div>
      <div class="block block-strong-ios block-outline-ios">
        <div class="range-slider range-slider-init" data-min="0" data-max="100" data-label="true" data-step="5"
          data-value="25" data-scale="true" data-scale-steps="5" data-scale-sub-steps="4"></div>
      </div>
      <div class="block-title">Vertical</div>
      <div class="block block-strong-ios block-outline-ios display-flex justify-content-center">
        <div class="range-slider range-slider-init margin-right" data-vertical="true" data-min="0" data-max="100"
          data-label="true" data-step="1" data-value="25" style="height: 160px"></div>
        <div class="range-slider range-slider-init margin-horizontal" data-vertical="true" data-min="0" data-max="100"
          data-label="true" data-step="1" data-value="50" style="height: 160px"></div>
        <div class="range-slider range-slider-init margin-horizontal" data-vertical="true" data-min="0" data-max="100"
          data-label="true" data-step="1" data-value="75" style="height: 160px"></div>
        <div class="range-slider range-slider-init margin-left" data-dual="true" data-vertical="true" data-min="0"
          data-max="100" data-label="true" data-step="1" data-value-left="25" data-value-right="75"
          style="height: 160px"></div>
      </div>
      <div class="block-title">Vertical Reversed</div>
      <div class="block block-strong-ios block-outline-ios display-flex justify-content-center">
        <div class="range-slider range-slider-init color-red margin-right" data-vertical="true"
          data-vertical-reversed="true" data-min="0" data-max="100" data-label="true" data-step="1" data-value="25"
          style="height: 160px"></div>
        <div class="range-slider range-slider-init color-red margin-horizontal" data-vertical="true"
          data-vertical-reversed="true" data-min="0" data-max="100" data-label="true" data-step="1" data-value="50"
          style="height: 160px"></div>
        <div class="range-slider range-slider-init color-red margin-horizontal" data-vertical="true"
          data-vertical-reversed="true" data-min="0" data-max="100" data-label="true" data-step="1" data-value="75"
          style="height: 160px"></div>
        <div class="range-slider range-slider-init color-red margin-left" data-dual="true" data-vertical="true"
          data-vertical-reversed="true" data-min="0" data-max="100" data-label="true" data-step="1" data-value-left="25"
          data-value-right="75" style="height: 160px"></div>
      </div>
    </div>
  </div>
</template>
<script>
  export default (props, { $f7, $el, $update }) => {
    let priceMin = 200;
    let priceMax = 400;

    const onPriceChange = (e) => {
      const range = $f7.range.get(e.target);
      priceMin = range.value[0];
      priceMax = range.value[1];
      $update();
    };

    return $render;
  };
</script>