Hot Line:

+1 (917) 730-2010

AI-Powered Web Development, SEO, Shopify & WordPress — Get a Free Consultation Today. Get Started

Tutorials

How To Add Price Range Slider in Shopify [Free Code]

  • 14 May, 2026
  • 0 Comments
  • By WebSensePro
How To Add Price Range Slider in Shopify [Free Code]

In today’s e-commerce world, providing a seamless shopping experience is key to increasing sales. Shopify’s default filters are great, but sometimes you want a more interactive and visually appealing way for customers to filter products. In this tutorial, we will show you how to add a custom Price Range Slider Filter to your Shopify Horizon theme for free.

This custom slider allows your customers to drag and select their preferred price range, making your collection pages more user-friendly.

Please follow the step-by-step code changes below to implement this feature.

Step 1: custom-price-filter.liquid File Code

Go to the Snippets folder in your theme files.

Create a new file named custom-price-filter.liquid.

Paste your provided slider code into this file and Save it.


{%- style -%}
  .custom-price-section {
    padding-top: {{ settings.section_padding_top | default: 15 }}px;
    padding-bottom: {{ settings.section_padding_bottom | default: 15 }}px;
    background: {{ settings.section_bg | default: '#ffffff' }};
    width: 100%;
    max-width: 300px;
  }

  .sidebar-filter-group {
    position: relative;
    width: 100%;
    font-family: inherit;
  }

  .sidebar-filter-group .price-filter-label {
    display: block;
    font-size: {{ settings.label_font_size | default: 16 }}px;
    font-weight: {{ settings.label_font_weight | default: '700' }};
    color: {{ settings.label_color | default: '#111111' }};
    margin-bottom: 20px;
  }

  .dual-slider-container {
    position: relative;
    width: 100%;
    height: 6px;
    margin: 10px 0 20px;
  }

  .slider-track {
    position: absolute;
    width: 100%;
    height: 6px;
    background: {{ settings.track_color | default: '#e0e0e0' }};
    border-radius: 5px;
    top: 0;
  }

  .slider-track-active {
    position: absolute;
    height: 6px;
    background: {{ settings.active_track_color | default: '#d32f2f' }};
    border-radius: 5px;
    top: 0;
  }

  input[type="range"].dual-range {
    -webkit-appearance: none;
    appearance: none;
    position: absolute;
    width: 100%;
    height: 6px;
    top: 0;
    left: 0;
    margin: 0;
    background: transparent !important;
    pointer-events: none;
  }

  input#price-min {
    background-color: {{ settings.track_color | default: '#e0e0e0' }} !important;
    height: 6px;
    border-radius: 5px !important;
  }

  input[type="range"].dual-range::-webkit-slider-runnable-track {
    height: 6px;
    background: transparent;
  }

  input[type="range"].dual-range::-moz-range-track {
    height: 6px;
    background: transparent;
  }

  input[type="range"].dual-range::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    height: 20px;
    width: 20px;
    border-radius: 50%;
    background: {{ settings.thumb_color | default: '#d32f2f' }};
    border: 3px solid {{ settings.thumb_border_color | default: '#ffffff' }};
    cursor: pointer;
    pointer-events: auto;
    margin-top: -7px;
    box-shadow: 0 1px 5px rgba(0,0,0,.3);
  }

  input[type="range"].dual-range::-moz-range-thumb {
    height: 20px;
    width: 20px;
    border-radius: 50%;
    background: {{ settings.thumb_color | default: '#d32f2f' }};
    border: 3px solid {{ settings.thumb_border_color | default: '#ffffff' }};
    cursor: pointer;
    pointer-events: auto;
  }

  .range-values-container {
    display: flex;
    justify-content: space-between;
    font-size: {{ settings.value_font_size | default: 14 }}px;
    font-weight: {{ settings.value_font_weight | default: '700' }};
    color: {{ settings.value_color | default: '#333333' }};
  }
{%- endstyle -%}
{%- liquid
  assign price_filter = collection.filters | where: "type", "price_range" | first

  if price_filter
    assign absolute_max = price_filter.range_max | divided_by: 100.0

   
    assign min_price = -1.0
    for product in collection.all_products
      assign product_min_price = product.price_min | divided_by: 100.0
      if min_price == -1.0 or product_min_price < min_price
        assign min_price = product_min_price
      endif
    endfor

    if min_price == -1.0
        assign min_price = 0.0
    endif

    if price_filter.min_value.value
      assign current_min = price_filter.min_value.value | divided_by: 100.0
    else
      assign current_min = min_price
    endif

    if price_filter.max_value.value
      assign current_max = price_filter.max_value.value | divided_by: 100.0
    else
      assign current_max = absolute_max
    endif

  else
    assign absolute_max = 1000.0
    assign min_price = 0.0
    assign current_min = 0.0
    assign current_max = 1000.0
  endif
%}

<div class="custom-price-section">
  <div class="sidebar-filter-group">
    <label class="price-filter-label">{{ settings.price_label_text | default: "Price:" }}</label>

<div class="dual-slider-container">
  <div class="slider-track"></div>
  <div class="slider-track-active" id="active-track"></div>

  <input
    type="range"
    id="price-min"
    class="dual-range"
    min="{{ min_price }}" 
    max="{{ absolute_max }}"
    value="{{ current_min }}"
    step="0.01">

  <input
    type="range"
    id="price-max"
    class="dual-range"
    min="{{ min_price }}" 
    max="{{ absolute_max }}"
    value="{{ current_max }}"
    step="0.01">
</div>
    <div class="range-values-container">
      <span id="price-min-display">{{ cart.currency.symbol }}{{ current_min | printf: "%.2f" }}</span>
      <span id="price-max-display">{{ cart.currency.symbol }}{{ current_max | printf: "%.2f" }}</span>
    </div>
  </div>
</div>

<script>
function initPriceSlider() {
  const minInput = document.getElementById('price-min');
  const maxInput = document.getElementById('price-max');
  const activeTrack = document.getElementById('active-track');
  const minDisplay = document.getElementById('price-min-display');
  const maxDisplay = document.getElementById('price-max-display');

  if (!minInput || !maxInput || !activeTrack) return;

  const currency = '{{ cart.currency.symbol }}';

  let filterTimeout;

  const formatter = new Intl.NumberFormat('en-US', {
    minimumFractionDigits: 2,
    maximumFractionDigits: 2
  });

  function updateSliderUI() {
    let minVal = parseFloat(minInput.value);
    let maxVal = parseFloat(maxInput.value);
    
    let rangeMin = parseFloat(minInput.min); 
    let rangeMax = parseFloat(minInput.max);

    if (minVal >= maxVal) {
      if (document.activeElement === minInput) {
        minInput.value = (maxVal - 0.01).toFixed(2);
      } else {
        maxInput.value = (minVal + 0.01).toFixed(2);
      }
      minVal = parseFloat(minInput.value);
      maxVal = parseFloat(maxInput.value);
    }
    
    const range = rangeMax - rangeMin;
    if (range <= 0) return;

    const percent1 = ((minVal - rangeMin) / range) * 100;
    const percent2 = ((maxVal - rangeMin) / range) * 100;

    activeTrack.style.left = percent1 + "%";
    activeTrack.style.width = (percent2 - percent1) + "%";

    minDisplay.textContent = currency + formatter.format(minVal);
    maxDisplay.textContent = currency + formatter.format(maxVal);
  }

  function applyFilter() {
    clearTimeout(filterTimeout);

    filterTimeout = setTimeout(() => {
      const params = new URLSearchParams(window.location.search);
      params.set('filter.v.price.gte', minInput.value);
      params.set('filter.v.price.lte', maxInput.value);

      window.location.search = params.toString();
    }, 700);
  }

  minInput.oninput = () => {
    updateSliderUI();
    applyFilter();
  };

  maxInput.oninput = () => {
    updateSliderUI();
    applyFilter();
  };

  updateSliderUI();
}

document.addEventListener('DOMContentLoaded', initPriceSlider);

const observer = new MutationObserver(() => {
  if (document.getElementById('price-min') && !document.getElementById('price-min').oninput) {
    initPriceSlider();
  }
});

observer.observe(document.body, { childList: true, subtree: true });

document.addEventListener('click', (e) => {
  if (e.target.closest('.active-facets__button-remove')) {
    setTimeout(initPriceSlider, 600);
  }
});
</script>

Step 2: settings_schema.json File Changes

Now we need to add the settings so you can control the colors and fonts directly from the Shopify Customizer.

Step 1: Open the settings_schema.json file .

Step 2: Find the closing bracket }, after the "theme_info" section

Step 3: Paste the following code right after it:

{
  "name": "Price-Filter",
  "settings": [
      {
  "type": "header",
  "content": "Price Filter Settings"
  },
  {
  "type": "text",
  "id": "price_label_text",
  "label": "Label Text",
  "default": "Price:"
  },
  {
  "type": "range",
  "id": "label_font_size",
  "min": 10,
  "max": 30,
  "step": 1,
  "unit": "px",
  "label": "Label Font Size",
  "default": 16
  },
  {
  "type": "select",
  "id": "label_font_weight",
  "label": "Label Font Weight",
  "options": [
    { "value": "400", "label": "Normal" },
    { "value": "500", "label": "Medium" },
    { "value": "600", "label": "Semi Bold" },
    { "value": "700", "label": "Bold" }
  ],
  "default": "700"
  },
  {
  "type": "color",
  "id": "label_color",
  "label": "Label Text Color",
  "default": "#111111"
  },
  {
  "type": "color",
  "id": "section_bg",
  "label": "Section Background",
  "default": "#ffffff"
  },
  {
  "type": "range",
  "id": "section_padding_top",
  "min": 0,
  "max": 50,
  "step": 1,
  "unit": "px",
  "label": "Padding Top",
  "default": 15
  },
  {
  "type": "range",
  "id": "section_padding_bottom",
  "min": 0,
  "max": 50,
  "step": 1,
  "unit": "px",
  "label": "Padding Bottom",
  "default": 15
  },
  {
  "type": "color",
  "id": "track_color",
  "label": "Slider Track Color",
  "default": "#e0e0e0"
  },
  {
  "type": "color",
  "id": "active_track_color",
  "label": "Active Track Color",
  "default": "#d32f2f"
},
{
  "type": "color",
  "id": "thumb_color",
  "label": "Thumb Color",
  "default": "#d32f2f"
},
{
  "type": "color",
  "id": "thumb_border_color",
  "label": "Thumb Border Color",
  "default": "#ffffff"
},
{
  "type": "range",
  "id": "value_font_size",
  "min": 10,
  "max": 24,
  "step": 1,
  "unit": "px",
  "label": "Price Text Size",
  "default": 14
},
{
  "type": "select",
  "id": "value_font_weight",
  "label": "Price Font Weight",
  "options": [
    { "value": "400", "label": "Normal" },
    { "value": "500", "label": "Medium" },
    { "value": "600", "label": "Semi Bold" },
    { "value": "700", "label": "Bold" }
  ],
  "default": "700"
},
{
  "type": "color",
  "id": "value_color",
  "label": "Price Text Color",
  "default": "#333333"
}

    ]
 },

Step 3: Render the Filter in filter.liquid

Now, we need to place the custom filter inside your theme’s filter file so it displays in the sidebar.

  • In your theme code editor.

  • Open the filter.liquid file.

  • Search for the term: “price-filter”.

Look for the rendering block that looks like this:

{%- render 'price-filter', filter: filter, filter_style: block_settings.filter_style, should_render_clear: should_render_clear, id_prefix: 'horizontal' -%}
  • Right below that line, paste the code to render your new custom slider:
{% render 'custom-price-filter' %}
  • Next, search for ‘filter-remove-buttons’ inside the same file. You will see a block of code that looks like this:
{% render 'filter-remove-buttons',
  filters: filters,
  results_url: results_url,
  show_filter_label: block_settings.show_filter_label,
  should_show_clear_all: false
%}
  • Cut this entire filter-remove-buttons block and paste it right under your new {% render 'custom-price-filter' %} code block.

  • Click Save.

Step 4: Hide the Default Price Filter (CSS Fix)

To prevent the default Shopify price filter from conflicting with your beautiful new custom slider, we need to hide the old one using CSS.

  • Go to the Assets folder in your theme files.

  • Open the base.css file.

  • Scroll to the very bottom of the file and paste this code:

accordion-custom:has([data-testid="price-filter"]) {
    display: none !important;
}

Step 5: Final Steps in Theme Customizer

  1. Go to Online Store > Themes > Customize.
  2. Navigate to any Collection Page.
  3. Click on Product Grid settings and ensure the Desktop filter layout is set to Vertical.
  4. To customize the look, go to Theme Settings (gear icon) and find the Price-Filter tab. Here you can adjust the labels, font sizes, and colors to match your brand.

4.9/5 · 242 votes
Tags:

    Comments

    Background Pattern

    Want to work with us?

    Let’s build your website, grow your traffic, and automate your business with AI.

    Background Pattern