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">
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;
}
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">
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">
----
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,
})
}
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,
})
}
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;
}
}
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)