Browser DOM question: Locking y scroll efficiently
Answered
gin posted this in #help-forum
ginOP
So I was asking if any of you guys have a simple and lightweight implementation of that?
Example: A simple drawer that opens from the bottom is displayed. We disable scrolling and enable it once the drawer closes.
We don't want to reset the scroll position.
I found this: https://www.npmjs.com/package/scroll-lock
Example: A simple drawer that opens from the bottom is displayed. We disable scrolling and enable it once the drawer closes.
We don't want to reset the scroll position.
I found this: https://www.npmjs.com/package/scroll-lock
24 Replies
ginOP
Usecase for that library: User scrolls over the initial viewport, setting a simple position fixed and a width of 100% will reset the y position back to initial. My current solution is to remember the y position before drawer opens and adjusting the top position of the fixed body.
Saving that position to a state and we can do that exact same thing when we remove fixed position from the body
But..... this brings some bugs. For example, On first Page load the position of y is reset cause reset lock is triggered for some reason. I have it in a useEffect cleanup function, so that could be the problem (Without that, the above implementation would not work)
Better context:
const [currentScroll, setCurrentScroll] = useState(0);
const lockScroll = () => {
const current = window.scrollY;
document.body.style.position = "fixed";
document.body.style.top = `-${current}px`;
document.body.style.width = "100%";
setCurrentScroll(current);
console.log("locking on position: ", current);
console.log("current scroll on locking now: ", currentScroll);
};
const unlockScroll = () => {
console.log("unlocking on position: ", currentScroll);
document.body.style.position = "";
document.body.style.top = "";
document.body.style.width = "";
window.scrollTo(0, currentScroll);
}
useEffect(() => {
console.log("current scroll changed: ", currentScroll);
}, [currentScroll]);
useEffect(() => {
function handleClickOutside(event: MouseEvent) {
if (drawerRef.current && !drawerRef.current.contains(event.target as Node)) {
setOpen(false);
unlockScroll();
}
}
if (open) {
const current = window.scrollY;
setCurrentScroll(current);
document.addEventListener("mousedown", handleClickOutside);
lockScroll();
}
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, [open]);https://www.npmjs.com/package/scroll-lock
This sounds interesting, but does someone have an idea how I can solve this problem by myself? Any topic or link is appreciated
This sounds interesting, but does someone have an idea how I can solve this problem by myself? Any topic or link is appreciated
Take a look at https://www.npmjs.com/package/react-modern-drawer?activeTab=readme 0 deps, and its very simple to understand, I just used the source to reverse engineer how they did it and it works without issue.
Answer
Gotcha, I try to do it without deps if I can but you do you 🙂
@Jboncz Gotcha, I try to do it without deps if I can but you do you 🙂
ginOP
what your implementation look like?
ive tried this and it didnt work
from the drawer lib u gave me
More or less, I made a few changes I think
not at pc anymore
ginOP
just setting overflow wont do the thing for me
that was the first thing that came to my mind
but it aint working
Then something is up with the rest of your styling
@Jboncz Then something is up with the rest of your styling
ginOP
yeah i do all my styling myself so it could be
Yeah, I would work backwards, or with a fresh set of css to see why its not working properly. Itll come to bite you alter
If you share a minimal reproduction of your stuff I can look at it