Intro
Discover techniques to programmatically show/hide scroll, default, and custom. Leverage the useScrollHide hook for enhanced control in Modals and components.
The use cases for the useScrollHide hook
Imagine you've Modal component and during display, you have double scroll. First is window scroll and the second scroll is inside Modal. It may cause weird UX and frustrating to use UI. The best approach to improve that is just disabling the scroll on window when Modal is displayed.
To understand the use case check the following GIF:
Loading
How our hook works in the context of Modal component
This hook may be used to hide/show scroll programmatically for window or other HTML elements. It may be useful when you create any component that appears on the screen and contains a scroll - menu, select, dialog, alert, ...etc.
How to use the useScrollHide hook?
We'll use our hook in 2 scenarios: with window and with any other HTML element.
Loading
If we want to use the scroll hide mechanism and apply it to HTML element, we need to pass the type of this element to our hook.
In addition, we have 2 methods to programmatically maintain the scroll.
Implementation process
Check the following GIF to understand how it was implemented step by step:
Loading
Implementation process
Let's start the explanation with boilerplate for our hook.
Loading
Now, we need a mechanism that determines what we should track (window or HTML element). We should pick the HTML element if the value of ref is assigned - different than null. Otherwise, it will be a window.
Loading
We want to hide the scroll just after the component is mounted. So, we need the effect. It will work like this:
- if the component is mounted - we'll call the 'hide' function to hide scroll,
- if the component is unmounted - we'll call the 'show' function to restore scroll.
Loading
We need to store initial styles for our target element in which we want to hide/show scroll. For that, we'll also use ref object. It's because it will store these values per hook usage and will not cause additional rerenders like useState hook.
Loading
Why the overflow value is auto by default? If the target element (window or HTML element) will not have a overflow, we want to set this value to auto - to make the scroll working as before.
Last but not least, we need to implement show and hide functions.
Loading
In each, at the beginning we get an element - the window or HTML element. Next, we are assigning styles to hide and show scroll.
Now, it will work, but we're using useEffect to perform some DOM operations - reading values and changing styles.
We've used useEffect, but we should use useLayoutEffect which is designed for that case - it's executed after browser repaints our view - so we will be sure that our styles data is up to date.
Loading
Last thing... Still, we need to take into consideration server-side rendering. Right now we'll have logged bad looking error/warning on server side (Next or Gatsby). To fix that we need to use abstraction for useLayoutEffect that blocks executing it on server-side.
Loading
I'm using useIsomorphicLayoutEffect in almost all hooks that I implemented if I want to use useLayoutEffect. If you want to understand what this hook does, check the following đ° Removing server warnings for useLayoutEffect with a custom hook article.
The complete implementation with tests and separated type definitions
Check the final code in the following Dream stack for React developer repository. Below you've snippets to explore and use in your projects.
Loading
Loading
Loading
Conclusions
Now you know how to hide scroll for dedicated UI components with a reusable hook. We've learned that server side code may prompt an error/warning if we use useLayoutEffect on the server.
- 1. Rendering
16 minutes
Creating portals with custom usePortal hook
2 m
We will change the screens with useStepper hook
3 m
Manage components appearance with useToggle hook
4 m
Removing server warnings for useLayoutEffect with custom hook
3 m
First interaction detection with useOnInteraction hook
4 m
- 2. Forms
4 minutes
- 3. Events
26 minutes
Read the scroll metadata and direction with useScroll hook
5 m
Using clipboard with useClipboard hook
4 m
Detect outside click with the useClickOutside hook
6 m
Deep dive into useIntersectionObserver hook
4 m
Element size measurement with useElementSize hook
7 m
- 4. Guards
5 minutes
- 5. Interactions
5 minutes
Comments
Add your honest opinion about this article and help us improve the content.