DEV Community

Aichurok Enazarova
Aichurok Enazarova

Posted on

Creating scrollable container

Scrollable containers very useful on mobile screens or when you just want to add some extra featured styles on your page.
In this article I will explain, how i could realize this task.


1) I created container inside of this container I put several items.

<div className="container__scrollable">
 <div className="scrollable__items">
      {props.items.map((el,i)=>{
          return(
             <div key={i} className="scroll__item">
                  <h3>{el.title}</h3>
                  <hr/>
                  <p>{el.text}</p>
              </div>)
       })}
 </div>
<div className="container__scrollable">

Enter fullscreen mode Exit fullscreen mode

2) I have limited the the main container to 1000px. And for a container that contains all the items I made "display: flex;" and "overflowX: auto;"

.container__scrollable{
  max-width: 1000px;
}
.scrollable__items{
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  overflow-x: auto;
  cursor: pointer;
}
.scrollable__items::-webkit-scrollbar{
  width: 0;
}

.scrollable__items > * > *{
  margin:20px;
}
.scroll__item {
  min-width: 260px;
  background-color: cornflowerblue;
  border-radius: 10px;
  margin: 10px;
  border: 1px solid gray;
}


Enter fullscreen mode Exit fullscreen mode

3) I have put events to the container with the className="scrollable__items"

<div className="container__scrollable">
 <div 
    className="scrollable__items" 
            onMouseLeave={onMouseLeave}
            onMouseDown={onMouseDown}
            onMouseUp={onMouseUp}
            onMouseMove={onMouseMove}

>
      {props.items.map((el,i)=>{
          return(
             <div key={i} className="scroll__item">
                  <h3>{el.title}</h3>
                  <hr/>
                  <p>{el.text}</p>
              </div>)
       })}
 </div>
<div className="container__scrollable">
Enter fullscreen mode Exit fullscreen mode

4) We need to import useRef and useState from react and use a ref in a container with classname="container__scrollable";

    let ref = useRef();
    const [state, setState] = useState({
        scrollX:0,
        clientX:0,
        isScrolling:false,
    })

-------------------------
<div className="container__scrollable">
 <div 
    className="scrollable__items" 
             ref={ref}
            onMouseLeave={onMouseLeave}
            onMouseDown={onMouseDown}
            onMouseUp={onMouseUp}
            onMouseMove={onMouseMove}

>
      {props.items.map((el,i)=>{
          return(
             <div key={i} className="scroll__item">
                  <h3>{el.title}</h3>
                  <hr/>
                  <p>{el.text}</p>
              </div>)
       })}
 </div>
<div className="container__scrollable">

----
Enter fullscreen mode Exit fullscreen mode

clientX is will be taken from event (event.clientX). ClientX is actually shows where users pointer is on X - axis, so more you go to left it decrease more right increase.
ShowX will be integer that we will use to scroll our container.

5)OnMouseUp and OnMouseLeave we dont want to our container scroll. Below in code shows how


      function onMouseUp(e){

          setState({
              ...state,
              isScrolling:false,
          })
      }

    function onMouseLeave(e){
        e.preventDefault();

        setState({
            ...state,
            isScrolling:false,
        })
    }
Enter fullscreen mode Exit fullscreen mode

So basically we just change our state "isScrolling: false".

6) Next we start our scrolling with mouseDown when we press left button of mouse but not yet released. Below in the code you will that we set our state to "isScrolling: true" and "clientX: e.clientX," , clientX to fix our clients pointer.


function onMouseDown(e){
          e.preventDefault();
          setState({
              ...state,
              isScrolling:true,
              clientX: e.clientX,
          })

}

Enter fullscreen mode Exit fullscreen mode

7) Next most difficult part is onMouseMove function that activates everytime when your mouse moves on the container where we are working on.

function onMouseMove(e){
          e.preventDefault()
          const {clientX, scrollX,isScrolling} = state;
          if(isScrolling){
              setState({
                  ...state,
                  scrollX: (scrollX - e.clientX) + clientX,
                  clientX: e.clientX,
              })

              ref.current.scrollLeft = scrollX;


          }

      }

Enter fullscreen mode Exit fullscreen mode

In this function we have ScrollX that calculates. ScrollX at the beginning is 0 then it substracts e.clientX. You will get negative integer if you scroll to right (if you want to see items on the right).


For example -400 but than you add clientX that was setAfter we calculated that number will be more than -400, for example 440, here difference will be 40.
We use 40 for our scroll conainer ref.current.scrollLeft = scrollX(40); And our container will open right side for 40 points or pixels.

7) than we just add to our container ref "ref.current.scrollLeft = scrollX;"

Top comments (0)