Why scrollWidth returns the same value of offsetWidth even when content overflows?

Viewed 310

I'm trying to create a simple drag n drop carousel.

In order to set the constraints of the inner carousel, I need to calculate the difference between scrollWidth and offsetWidth. Unexpectedly, I get the same value for both. This shouldn't be happening, since the content overflows its parent div.

const fotos = [picOne, picTwo, picThree, picFour]

export const App = () => {
  
  const [width, setWidth] = useState(0)
  const ref = useRef(null)
  
  useEffect(() => {
    setWidth(ref.current.scrollWidth - ref.current.offsetWidth)
  }, [])

  return (
    <>
      <div className="carousel" ref={ref}>
        <motion.div className="carousel-insider"
                    drag="x"
                    dragConstraints={{right: 0, left: -width}}>
        
          {fotos.map((foto, index) => <img key={index} src={foto}/>)}
        </motion.div>
      </div>
    </>
  )
}

Carousel code: https://jsfiddle.net/oa6tLrfq/

What am I doing wrong here?

1 Answers

Ok, I've come up with a work around.

What caused that issue?

All elements widths' were dependent upon html and body widths. This was caused by defining all widths as a percentage. Somehow, this caused a delay between rendering the component and scrollWidth getting, in fact, the correct value.

What's the work around?

  1. You can use a setTimeout inside useEffect to delay its beginning. 3 seconds worked for me.

     useEffect(() => {
     setTimeout(setWidth(ref.current.scrollWidth - ref.current.offsetWidth)}, 3), [])
    
  2. You can wrap img with a div and set a fixed width for the div.

Related