1

React developer here, trying to learn by coding, here i have a slider which im trying to make thumb bigger but it does not get bigger than input where it is(as you can see if i make thumb bigger it wont show it fully). Any advice on how to make that look like the one i want?

English is not my mother language so could be mistakes.

so here is my slider:

enter image description here

i want it to look like this:

enter image description here

what i have done already:

https://codesandbox.io/s/tender-architecture-s4we0m?file=/src/styles.css

css:

.App {
  font-family: sans-serif;
  text-align: center;
}

@media screen and (-webkit-min-device-pixel-ratio: 0) {
  input[type="range"] {
    overflow: hidden;
    width: 80px;
    /* -webkit-appearance: none; */
    background-color: white;
  }

  input[type="range"]::-webkit-slider-runnable-track {
    height: 10px;
    /* -webkit-appearance: none; */
    color: #13bba4;
    margin-top: -1px;
  }

  input[type="range"]::-webkit-slider-thumb {
    width: 10px;
    /* -webkit-appearance: none; */
    height: 20px;
    cursor: ew-resize;
    background: #434343;
    box-shadow: -80px 0 0 80px #ce7c00;
  }
}
/** FF*/
input[type="range"]::-moz-range-progress {
  background-color: #43e5f7;
}
input[type="range"]::-moz-range-track {
  background-color: #9a905d;
}
/* IE*/
input[type="range"]::-ms-fill-lower {
  background-color: #43e5f7;
}
input[type="range"]::-ms-fill-upper {
  background-color: #9a905d;
}

js:

import { TransformWrapper, TransformComponent } from "react-zoom-pan-pinch";
import { useRef, useState } from "react";
import "./styles.css";
// Style
const MainWrapper = {
  background: "salmon",
  width: "100%",
  height: "100vh",
  position: "relative"
};

const InputWrapper = {
  position: "fixed",
  zIndex: 9999,
  width: "100%"
};

const ScaleIndicator = {
  textAlign: "right",
  position: "absolute",
  right: "40px",
  background: "blue",
  color: "white",
  zIndex: "1000",
  padding: "10px"
};

const Slider = {
  width: "200px",
  margin: "10px 30px"
};

export default function App() {
  const transformComponentRef = useRef(null);
  const [scale, setScale] = useState(0.7);

  const updateScale = (e) => {
    const targetScale = parseFloat(e.target.value);
    const factor = Math.log(targetScale / scale);
    const { zoomIn, zoomOut } = transformComponentRef.current;

    /*
      how react-zoom-pan-pinch calculate new scale :
      targetScale = scale * Math.exp(1 * factor);

      we need factor(step) for zoomIn and zoomOut, just reverse the previous equation to get factor
      factor = Math.log(targetScale / currentScale);
    */
    // console.log(scale * Math.exp(1 * factor), newScale);

    // const targetScale = scale * Math.exp(1 * factor);

    if (targetScale > scale) {
      zoomIn(factor, 0);
    } else {
      zoomOut(-factor, 0);
    }

    setScale(targetScale);
  };

  return (
    <div style={MainWrapper}>
      <h1 style={ScaleIndicator}>{(scale * 100).toFixed(0)}%</h1>
      <div style={InputWrapper}>
        <input
          type="range"
          min="0.1"
          max="1.5"
          step="0.01"
          value={scale}
          onChange={updateScale}
          style={Slider}
        />
      </div>
      <TransformWrapper
        ref={transformComponentRef}
        onZoomStop={(e) => {
          setScale(e.state.scale);
        }}
        initialScale={scale}
        minScale={0.1}
        maxScale={1.5}
        doubleClick={{
          disabled: true
        }}
        // wheel={{
        //   activationKeys: ["z"]
        // }}
        // panning={{
        //   activationKeys: ["x"],
        // }}
        limitToBounds={false}
        zoomAnimation={{ disabled: true }}
        centerOnInit
        onZoom={(e) => {
          setScale(e.state.scale);
        }}
      >
        {({ zoomIn, zoomOut, setTransform, ...rest }) => {
          return (
            <TransformComponent
              wrapperStyle={{
                width: "100%",
                height: "100%"
              }}
            >
              <img
                src="https://images.pexels.com/photos/2450218/pexels-photo-2450218.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"
                alt="Cool Astro"
              />
            </TransformComponent>
          );
        }}
      </TransformWrapper>
    </div>
  );
}

that link i provided looks totally different with firefox browser, idea on that also ?

walee
  • 575
  • 4
  • 16
  • any help is appreciated – walee Apr 05 '22 at 13:06
  • I assume you got your CSS from [here](https://stackoverflow.com/questions/18389224/how-to-style-html5-range-input-to-have-different-color-before-and-after-slider/38163892#38163892) - as noted in the comments, this doesn't account for the thumb not being able to be bigger than the track due to overflow: hidden. The [other popular answer](https://stackoverflow.com/questions/18389224#57153340) addresses this. – James Whiteley Apr 05 '22 at 14:04
  • Does this answer your question? [How to style HTML5 range input to have different color before and after slider?](https://stackoverflow.com/questions/18389224/how-to-style-html5-range-input-to-have-different-color-before-and-after-slider) – James Whiteley Apr 05 '22 at 14:04
  • Those are in pure javascript, could you possibly write an answer in React so that others could learn that in React and i could accept ur answr, my js is weak… – walee Apr 05 '22 at 21:08

4 Answers4

0

There are multiple ways to style the <input type="range" /> element as already pointed out here. If you don't care about the pure CSS solution then with React, you can simply take advantage of the input onChange event to grab the input element with e.currentTarget and apply the necessary stylings to change the appearance mentioned in the post above

<input 
  onChange={(e) => {
    updateStyles(e.currentTarget);
  }}
/>

I'd also suggest getting familiar with the useRef & useEffect hooks, this ensures that the styles also get applied on the initial render.

Here's your modified example

htmn
  • 1,505
  • 2
  • 15
  • 26
0

Slider react component. You can add some props to value, min, max, two way binding to control it from parent component and improve it. Sandbox example

There is a problem with thumb. In chrome if you want the thumb to be larger than the track, then the box shadow overlaps the track with the height of the thumb.

Just sumup all these answers and wrote normally working slider with larger slider thumb. Related answer

const Slider = () => {
  const inputRef = useRef();
  const [value, setValue] = useState(25);

  const onChange = (event) => {
    setValue(event.target.checked);
  };

  const initSlider = () => {
    const slider = inputRef.current;
    const min = slider.min;
    const max = slider.max;
    const value = slider.value;

    slider.style.background = `linear-gradient(to right, red 0%, red ${
      ((value - min) / (max - min)) * 100
    }%, #DEE2E6 ${((value - min) / (max - min)) * 100}%, #DEE2E6 100%)`;

    slider.oninput = function () {
      this.style.background = `linear-gradient(to right, red 0%, red ${
        ((this.value - this.min) / (this.max - this.min)) * 100
      }%, #DEE2E6 ${
        ((this.value - this.min) / (this.max - this.min)) * 100
      }%, #DEE2E6 100%)`;
    };
  };

  useEffect(() => {
    initSlider();
  });

  return (
    <input
      ref={inputRef}
      id="slider"
      onChange={onChange}
      type="range"
      min={0}
      defaultValue={value}
      max={100}
    />
  );
};

P.S. Maybe, there is some mistakes, because I used to code on vue.js. I tried my best)

abdigali
  • 247
  • 2
  • 5
-1

Can you please try this CSS code in your slider thumb class? I think it will work :)

you can use this link as well

https://toughengineer.github.io/demo/slider-styler/slider-styler.html

 input[type=range]::-webkit-slider-thumb {
      cursor: ew-resize;
      background: #434343;
      box-shadow: -100px 0 0 100px #ce7c00;
      -webkit-appearance: none;  
      border: none;
      height: 20px;
      width: 20px;
      border-radius: 50%;
      background: #434343;
      margin-top: -7px;
    }
Milan Sachani
  • 335
  • 3
  • 8
-1

For general styling of range input look at this great article styling cross browser compatible range inputs css

This covers most of the things you can do with input ranges and also author created a site to create input ranges. range.css - generate styles for your HTML5 Inputs by Daniel Stern

To be able to change the color of lower and upper part of the slider in Chrome you have to write a little bit of js code, for that you can check this thread Style lower and upper fill in HTML5 range input

qublaidev
  • 69
  • 4