How to Make a Custom Slider Component in Vue
Creating a custom slider component can be tricky, especially if you want to create a lean standalone Vue component. In this quick article, you’ll learn how to build a fully customizable slider component in Vue. Feel free to swap out the majority of the CSS to get the styling you want, but I’ll give you a good jumping-off point.
In fact, the component we’ll be building is the exact same component that we use in production, and you can see it in action in the signup workflow for our coding courses.
You can see a full demo on codesandbox here. If you’re like me, you prefer to build your own lightweight UI components, rather than import a bloaty library that you don’t have the ability to modify and change easily.
The HTML
<template>
<div>
<div class="slider-component">
<div class="slidecontainer">
<input
ref="input"
v-model="currentValue"
type="range"
:min="min"
:max="max"
class="slider"
@input="onInput"
/>
</div>
</div>
</div>
</template>
That wasn’t so bad right? We are building out the data model in such a way the to use the component we can sue the built-in v-model property.
The JavaScript
export default {
props: {
value: {
type: Number,
required: true,
},
min: {
type: Number,
required: true,
},
max: {
type: Number,
required: true,
},
},
data() {
return {
currentValue: this.value,
};
},
methods: {
onInput() {
// this.currentValue is a string because HTML is weird
this.$emit("input", parseInt(this.currentValue));
},
},
};
Like I mentioned above, this sets up the use of v-model. We set the default currentValue to the this.value prop, and by emitting the current value with the @input hook, we are good to go.
The CSS
You may not be here for exactly my styling, but you’re probably here so that you can swap out the styling. Feel free to copypasta my CSS and swap it our for your own sutff!
.slider-component .slidecontainer {
width: 100%;
}
.slider-component .slidecontainer .slider {
-webkit-appearance: none;
appearance: none;
width: 100%;
height: 4px;
border-radius: 2px;
background: #c2c2c2;
outline: none;
opacity: 0.7;
-webkit-transition: 0.2s;
transition: opacity 0.2s;
}
.slider-component .slidecontainer .slider:hover {
opacity: 1;
}
.slider-component .slidecontainer .slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 18px;
height: 18px;
background: #d8a22e;
cursor: pointer;
border-radius: 50%;
}
.slider-component .slidecontainer .slider::-moz-range-thumb {
width: 18px;
height: 18px;
background: #d8a22e;
cursor: pointer;
border-radius: 50%;
}
The important thing to note here is that we’re overriding the browsers defaults and setting up all of our own stuff.
Full Component
<template>
<div>
<div class="slider-component">
<div class="slidecontainer">
<input
ref="input"
v-model="currentValue"
type="range"
:min="min"
:max="max"
class="slider"
@input="onInput"
/>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
value: {
type: Number,
required: true,
},
min: {
type: Number,
required: true,
},
max: {
type: Number,
required: true,
},
},
data() {
return {
currentValue: this.value,
};
},
methods: {
onInput() {
// this.currentValue is a string because HTML is weird
this.$emit("input", parseInt(this.currentValue));
},
},
};
</script>
<style scoped>
.slider-component .slidecontainer {
width: 100%;
}
.slider-component .slidecontainer .slider {
-webkit-appearance: none;
appearance: none;
width: 100%;
height: 4px;
border-radius: 2px;
background: #c2c2c2;
outline: none;
opacity: 0.7;
-webkit-transition: 0.2s;
transition: opacity 0.2s;
}
.slider-component .slidecontainer .slider:hover {
opacity: 1;
}
.slider-component .slidecontainer .slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 18px;
height: 18px;
background: #d8a22e;
cursor: pointer;
border-radius: 50%;
}
.slider-component .slidecontainer .slider::-moz-range-thumb {
width: 18px;
height: 18px;
background: #d8a22e;
cursor: pointer;
border-radius: 50%;
}
</style>
Related Articles
How to Make a Simple Vue Custom Select Component
Sep 25, 2020 by Lane Wagner - Boot.dev co-founder and backend engineer
Creating a custom select tag with its own styling is notoriously difficult. Sometimes it’s impossible to build from scratch without a combination of styled divs and custom JavaScript. In this article, you’ll learn how to create a custom select component in Vue that can be easily styled with your own CSS. In fact, it’s the same component we use in production on boot.dev, and you can see it in action on our JavaScript playground.
Creating a Custom Tooltip Component in Vue
Aug 28, 2020 by Lane Wagner - Boot.dev co-founder and backend engineer
There are plenty of libraries out there that will have you up and running with a good tooltip solution in minutes. However, if you are like me, you are sick and tired of giant dependency trees that have the distinct possibility of breaking at any time. For that reason, we’re going to build a custom single file tooltip component that you can build yourself and tweak to your heart’s content. It might take 15 minutes instead of 3… sorry about that.
How to Create a Custom Toggle Switch Component in Vue.js
Jul 21, 2020 by Lane Wagner - Boot.dev co-founder and backend engineer
Custom toggle switches are a pain to code from scratch. So many lines for such a simple UI widget! In this quick tutorial, we will learn how to build a fully encapsulated toggle switch component in Vue.js. The component we’re building is used currently on boot.dev’s login page. Go take a look to see a live demo.
Vue History Mode - Support Legacy Hash URLs
Jul 15, 2020 by Lane Wagner - Boot.dev co-founder and backend engineer
When we first launched the boot.dev’s single-page-app, we were using Vue Router’s default hash routing. Hash routing looks ugly to the end-user, and when you want to be able to share parts of your app via direct link those hashes can get really annoying.