![How To Add Price Range Slider in Shopify [Free Code]](/_astro/how-to-add-price-range-slider-in-shopify-free-code.CiGc8m-J_Z1DlAxL.webp)
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.liquidfile. -
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-buttonsblock 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.cssfile. -
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
- Go to Online Store > Themes > Customize.
- Navigate to any Collection Page.
- Click on Product Grid settings and ensure the Desktop filter layout is set to Vertical.
- 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.


![How to Install Any Claude Skill From GitHub [Step-by-step] - Beginner Tutorial](/_astro/How%20to%20Install%20Any%20Claude%20Skill%20From%20GitHub%20_Step-by-step_%20-%20Beginner%20Tutorial.Cgks_FcS_1swru6.webp)
.Bktem256_23EEnI.webp)
.rrgOIsSz_Z2n0to0.webp)
![Image related to how to add price range slider in shopify [free code]](/_astro/how-to-add-price-range-slider-in-shopify-free-code.CiGc8m-J_2dhLPH.webp)

