Align Thumb of React Range Slider so it doesn't go outside bounding box

Viewed 733

I am trying to make a range slider & I want to make the thumb (indigo) not go outside the bounding box border (red).

align thumb of range slider

If the thumb is small, then it looks perfect but if the thumb is big, which it is in my case, then it looks out of alignment.

I am using React & Tailwind with the help of react-range library & the code looks like:

import * as React from "react"
import { Range } from "react-range"

export default function App() {
    const [values, setValues] = React.useState([50])

    return (
        <div className="w-full flex justify-center">
            <div className="w-48 border-4 border-red-300">
                <h1 className="text-4xl">Range</h1>
                <label>Slider</label>
                <Range
                    step={1}
                    min={0}
                    max={75}
                    values={values}
                    onChange={(values) => {
                        setValues(values)
                    }}
                    renderTrack={({ props, children }) => (
                        <div
                            {...props}
                            className="w-full h-3 pr-2 my-4 bg-gray-200 rounded-md"
                        >
                            {children}
                        </div>
                    )}
                    renderThumb={({ props }) => (
                        <div
                            {...props}
                            className="w-5 h-5 transform translate-x-10 bg-indigo-500 rounded-full focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
                        />
                    )}
                />
                <span>{values[0]}px</span>
            </div>
        </div>
    )
}

I have also made a reproducible demo → https://codesandbox.io/s/react-tailwind-align-range-slider-ghyf0?file=/src/App.tsx

I want the thumb to be in alignment with Slider & 0px otherwise it looks off. Even the native range slider doesn't go outside the bounding box. How can I achieve that effect?

2 Answers

I had exactly the same issue and I found this hacky solution.

In my case, thumb size is 16 x 16px with 2px track height.

const SliderTrack = styled.div`
    height: 2px;
    width: calc(100% - 16px);
    align-self: center;
    position: relative;

    &::before {
      content: '';
      display: inherit;
      height: 2px;
      width: 8px;
      transform: translate(-8px, 2px);
      background-color: 'red';
      z-index: -1;
    }

    &::after {
      content: '';
      display: inherit;
      height: 2px;
      width: 8px;
      transform: translate(8px, -2px);
      background-color: 'green';
      z-index: -1;
      position: absolute;
      right: 0;
    }
`;

I ended up using react-slider instead that remains inside the bounding box.

import * as React from "react"
import { Range } from "react-range"
import ReactSlider from "react-slider"

export default function App() {
    const [values, setValues] = React.useState([0])
    const [value, setValue] = React.useState(0)

    return (
        <div className="w-full flex justify-center">
            <div className="w-48 border-4 border-red-300">
                <h1 className="text-4xl">Range</h1>
                <label>React Range</label>
                <Range
                    step={1}
                    min={0}
                    max={75}
                    values={values}
                    onChange={(values) => {
                        setValues(values)
                    }}
                    renderTrack={({ props, children }) => (
                        <div
                            {...props}
                            className="w-full h-3 pr-2 my-4 bg-gray-200 rounded-md"
                        >
                            {children}
                        </div>
                    )}
                    renderThumb={({ props }) => (
                        <div
                            {...props}
                            className="w-5 h-5 transform translate-x-10 bg-indigo-500 rounded-full focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
                        />
                    )}
                />
                <span>{values[0]}px</span>
                <br />
                <br />
                <hr />
                <br />
                <label>React Slider</label>
                <ReactSlider
                    step={1}
                    min={0}
                    max={75}
                    className="w-full h-3 pr-2 my-4 bg-gray-200 rounded-md cursor-grab"
                    thumbClassName="absolute w-5 h-5 cursor-grab bg-indigo-500 rounded-full focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 -top-2px"
                    value={value}
                    onChange={(value: any) => {
                        setValue(value)
                    }}
                />
                <span>{value}px</span>
            </div>
        </div>
    )
}

The positioning is little off on Codesandbox but it works on my app by giving a little bit of absolute positioning :)

Codesandbox → https://codesandbox.io/s/react-tailwind-align-range-slider-ghyf0?file=/src/App.tsx

react-slider

Related