Creating a complex component in React from scratch can be challenging at times. But if you really want to hone your JavaScript and CSS skills, then...
For further actions, you may consider blocking this person and/or reporting abuse
Nice job, really helpful article!
Little heads up for people looking at this implementation, I noticed that the
outline: none
plus lack of a focus state on the thumb makes this not good for keyboard users as you can't tell it's focused at all, so a bit of work would be needed to make it clear when each thumb has focusThanks so much Sandra! I have to implement this and your code was very very helpful. I did a couple of changes in order to make get my final results in all the browser, I'll be very glad if you can tell me what do you think about it. Thanks so much for all!
codesandbox.io/s/bold-wildflower-q...
This was wonderful!!! I had to remove the functions from the useEffect dependency arrays, but after that this worked wonders!
Great job this helped me meet the deadline of my task, thank you.
Hey I am trying to use your slider with react-tables so your slider is acting as a filter. This requires the slider to be in a
<th>
. This poses an issue because on smaller screen sizes the slider seems to grow outside of the<th>
that it is inside. How can I control the horizontal size of the slider so it is smaller? Everything I do seems to fail miserably. Thanks in advance for anyone who helps :)I figured it out if you wrap the react-table filter display function in a div with position relative, you can then set the width of the other fields to 100 and they won't overlap. Notice the
w-100
class.<div className="mt-3 pb-5 w-100">
<div className="slider w-100">
<div className="slider__track" />
<div ref={range} className="slider__range" />
<div className="slider__left-value text-dark">{minVal}</div>
<div className="slider__right-value text-dark">{maxVal}</div>
</div>
<input
type="range"
min={minWeight}
max={maxWeight}
value={minVal}
ref={minValueRef}
onChange={(event) => {
const value = Math.min(Number(event.target.value), maxVal - 1);
setMinVal(value);
event.target.value = value.toString();
}}
className={"thumb thumb--zindex-3 w-100"}
/>
<input
type="range"
min={minWeight}
max={maxWeight}
value={maxVal}
ref={maxValueRef}
onChange={(event) => {
const value = Math.max(+event.target.value, minVal + 1);
setMaxVal(value);
event.target.value = value.toString();
}}
className="thumb thumb--zindex-4 w-100"
/>
</div>
Thanks! It was good learning of react and usage of ref.
Can you please elloborate z-index condition in first input tag : zIndex: minVal > max - 100 && "5" . Also it is not working when we are using react with typescript.
Thanks!
Check out this image: dev-to-uploads.s3.amazonaws.com/up...
I've explained the reason why the inline z-index style is needed over there, hope that clears your doubt.
I did this initially with TypeScript and it worked. The only difference is you got to specify the types.
Here's the TypeScript version: codesandbox.io/s/b9l0g
Thank you so much for explanation and typescript code.It was great learning experience.😊
You're welcome, glad it helped 😊
I've got two hints for you, add them if you like. :)
This callback is actually just a function call.
// Convert Number to percentage
function getPercent(value) {
return Math.round(((value - min) / (props.max - min)) * 100);
}
You don't need refs for the inputs, if you set the value directly onChange.
onChange={(e) => {
const value = Math.min(Number(e.target.value), maxVal);
e.target.value = value;
setMinVal(value);
}
I did try using
getPercent
as a simple function initially, but ended up getting the below ESLint warning.You are right about not using refs in the
onChange
events. I've made the changes above. Thank you for pointing that out.Hey! It was good to learn something new using react.
I have one observation if you see in Mozilla browser the thumb looks behind the slider range(working fine in Chrome), i have dig into this but couldn't found the fix, can you please help me with this.
checkout this image for Mozilla
dev-to-uploads.s3.amazonaws.com/up...
Chrome:
dev-to-uploads.s3.amazonaws.com/up...
Oh yes, I built this component only for Chrome browsers, forgot to mention that.
I've updated the CSS above and have included Firefox support. You need to use the pseudo-element
::-moz-range-thumb
to support Firefox browsers.Add the below code and it should work.
Also, make sure you don’t combine
.thumb::-moz-range-thumb
with.thumb::-webkit-slider-thumb
even though the styles remain the same. Add these classes along with its styles separately, or else it won’t work.Good one! I like the use of
ref
here. 😁Thank you 😁
Great insights here, had a lot of learning. Thanks.
You're welcome. Glad to hear that.
Thank you, it is very useful experience for me, to create a range with 2 sliders.
You're welcome, glad it helped.
Hey, thanks so much for this!
I actually saw your solution on codepen first and tried to implement it in my project. However, I have problems with setting the width.
I want to use the slider-component inside a grid element where the slider should span over the full width of that element. But when I set the width of .slider and .thumb to 100%, the thumbs are not displayed in the right position anymore.
I also described my problem here.
Is there a way to fix this? Thanks in advance for any help!
Ok it took me a while, but now I understand the answer further below :D
Simply add a position: relative to an outer container. This way, the thumbs orient their position to that container. Add top: 0px; to the thumb class and done :)
Can you tell what changes can I make so it fills the width of its container, looks like setting 100% causing problems in design
you should add return in getPercent function otherwise it will not return undefined and range will not work.
Thank you very much Sandra, very useful! I made few changes according to my needs...