barneycarroll / README.md
Useful for when a blocking user experience is needed (in my case, didn’t want people unwittingly loosing their place by scrolling while a modal required their attention): $.scrollLock() locks the body in place, preventing scroll until it is unlocked.
// Locks the page if it's currently unlocked $.scrollLock(); // . or vice versa $.scrollLock(); // Locks the page $.scrollLock( true ); // Unlocks the page $.scrollLock( false );
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
$ . scrollLock = ( function scrollLockClosure ( ) |
‘use strict’ ; |
var $html = $ ( ‘html’ ) , |
// State: unlocked by default |
locked = false , |
// State: scroll to revert to |
prevScroll = |
scrollLeft : $ ( window ) . scrollLeft ( ) , |
scrollTop : $ ( window ) . scrollTop ( ) |
> , |
// State: styles to revert to |
prevStyles = < >, |
lockStyles = |
‘overflow-y’ : ‘scroll’ , |
‘position’ : ‘fixed’ , |
‘width’ : ‘100%’ |
> ; |
// Instantiate cache in case someone tries to unlock before locking |
saveStyles ( ) ; |
// Save context’s inline styles in cache |
function saveStyles ( ) |
var styleAttr = $html . attr ( ‘style’ ) , |
styleStrs = [ ] , |
styleHash = < >; |
if ( ! styleAttr ) |
return ; |
> |
styleStrs = styleAttr . split ( / ; \s / ) ; |
$ . each ( styleStrs , function serializeStyleProp ( styleString ) |
if ( ! styleString ) |
return ; |
> |
var keyValue = styleString . split ( / \s : \s / ) ; |
if ( keyValue . length < 2 ) |
return ; |
> |
styleHash [ keyValue [ 0 ] ] = keyValue [ 1 ] ; |
> ) ; |
$ . extend ( prevStyles , styleHash ) ; |
> |
function lock ( ) |
var appliedLock = < >; |
// Duplicate execution will break DOM statefulness |
if ( locked ) |
return ; |
> |
// Save scroll state. |
prevScroll = |
scrollLeft : $ ( window ) . scrollLeft ( ) , |
scrollTop : $ ( window ) . scrollTop ( ) |
> ; |
// . and styles |
saveStyles ( ) ; |
// Compose our applied CSS |
$ . extend ( appliedLock , lockStyles , |
// And apply scroll state as styles |
‘left’ : — prevScroll . scrollLeft + ‘px’ , |
‘top’ : — prevScroll . scrollTop + ‘px’ |
> ) ; |
// Then lock styles. |
$html . css ( appliedLock ) ; |
// . and scroll state |
$ ( window ) |
. scrollLeft ( 0 ) |
. scrollTop ( 0 ) ; |
locked = true ; |
> |
function unlock ( ) |
// Duplicate execution will break DOM statefulness |
if ( ! locked ) |
return ; |
> |
// Revert styles |
$html . attr ( ‘style’ , $ ( » ) . css ( prevStyles ) . attr ( ‘style’ ) || » ) ; |
// Revert scroll values |
$ ( window ) |
. scrollLeft ( prevScroll . scrollLeft ) |
. scrollTop ( prevScroll . scrollTop ) ; |
locked = false ; |
> |
return function scrollLock ( on ) |
// If an argument is passed, lock or unlock depending on truthiness |
if ( arguments . length ) |
if ( on ) |
lock ( ) ; |
> |
else |
unlock ( ) ; |
> |
> |
// Otherwise, toggle |
else |
if ( locked ) |
unlock ( ) ; |
> |
else |
lock ( ) ; |
> |
> |
> ; |
> ( ) ) ; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
$ . scrollLock = ( function scrollLockSimple ( ) |
var locked = false ; |
var $body ; |
var previous ; |
function lock ( ) |
if ( ! $body ) |
$body = $ ( ‘body’ ) ; |
> |
previous = $body . css ( ‘overflow’ ) ; |
$body . css ( ‘overflow’ , ‘hidden’ ) ; |
locked = true ; |
> |
function unlock ( ) |
$body . css ( ‘overflow’ , previous ) ; |
locked = false ; |
> |
return function scrollLock ( on ) |
// If an argument is passed, lock or unlock depending on truthiness |
if ( arguments . length ) |
if ( on ) |
lock ( ) ; |
> |
else |
unlock ( ) ; |
> |
> |
// Otherwise, toggle |
else |
if ( locked ) |
unlock ( ) ; |
> |
else |
lock ( ) ; |
> |
> |
> ; |
> ( ) ) ; |
Saved searches
Use saved searches to filter your results more quickly
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session.
🔨 Cross-browser JavaScript library to disable scrolling page
License
FL3NKEY/scroll-lock
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Sign In Required
Please sign in to use Codespaces.
Launching GitHub Desktop
If nothing happens, download GitHub Desktop and try again.
Launching GitHub Desktop
If nothing happens, download GitHub Desktop and try again.
Launching Xcode
If nothing happens, download Xcode and try again.
Launching Visual Studio Code
Your codespace will open once ready.
There was a problem preparing your codespace, please try again.
Latest commit
Git stats
Files
Failed to load latest commit information.
README.md
Cross-browser JavaScript library to disable scrolling page
- More advanced touch event handling algorithm
- Horizontal scrolling support
- Support for nested scrollable elements
- Support for nested textarea and contenteditable
- New API
npm install scroll-lock # or yarn add scroll-lock
//es6 import import disablePageScroll, enablePageScroll > from 'scroll-lock'; //or import scrollLock from 'scroll-lock'; scrollLock.disablePageScroll(); //. //require const scrollLock = require('scroll-lock'); scrollLock.disablePageScroll(); //.
script src pl-s">path/to/scroll-lock.min.js">script> script> scrollLock.disablePageScroll(); //. script>
The es6 import will be used further in the examples, but these methods will also be available from the scrollLock object.
When you call the disablePageScroll method, scrolling is also disabled in iOS and other touch devices (essence of the problem). But scrolling on touch devices will be disabled on all elements. To do this, you must explicitly specify which element will scroll on the page.
import disablePageScroll, enablePageScroll > from 'scroll-lock'; //Get the element that should scroll when page scrolling is disabled const $scrollableElement = document.querySelector('.my-scrollable-element'); //Pass the element to the argument and disable scrolling on the page disablePageScroll($scrollableElement); // Also, pass the element to the argument and enable scrolling on the page enablePageScroll($scrollableElement);
Alternatively, you can specify the data-scroll-lock-scrollable attribute of the scrollable element.
div class pl-s">my-scrollable-element" data-scroll-lock-scrollable>div>
textarea and contenteditable
If a textarea or contenteditable is nested in a scrollable element, then do not worry, they will scroll without explicit indication.
When the disablePageScroll method is called, the scroll-lock indicates overflow: hidden; for body , thereby hiding the scroll bar. In some operating systems, the scroll bar has its physical width on the page, thus we get the effect of «displacement»:
To prevent this, scroll-lock calculates the scroll bar width when calling the disablePageScroll method and fills in the space for the body element.
But this does not work for elements with fixed positioning. To do this, you must explicitly indicate which element needs to fill in the space.
import addFillGapTarget, addFillGapSelector > from 'scroll-lock'; //selector addFillGapSelector('.my-fill-gap-selector'); //element const $fillGapElement = document.querySelector('.my-fill-gap-element'); addFillGapTarget($fillGapElement);
Or you can specify the data-scroll-lock-fill-gap attribute.
div class pl-s">my-fill-gap-element" data-scroll-lock-fill-gap>div>
A call to the disablePageScroll method creates a queue of calls. If you call the disablePageScroll method twice in a row, and then enablePageScroll , the page scrolling is not activated, because the enablePageScroll method will need to be called a second time.
If for some reason you need to activate scrolling the page out of turn, use the clearQueueScrollLocks method:
import disablePageScroll, clearQueueScrollLocks > from 'scroll-lock'; disablePageScroll(); disablePageScroll(); disablePageScroll(); disablePageScroll(); enablePageScroll(); console.log(getScrollState()); //false clearQueueScrollLocks(); enablePageScroll(); console.log(getScrollState()); //true
Hides the scroll bar and disables page scrolling.
import disablePageScroll > from 'scroll-lock'; const $scrollableElement = document.querySelector('.my-scrollable-element'); disablePageScroll($scrollableElement);
Shows the scroll bar and enables page scrolling.
import enablePageScroll > from 'scroll-lock'; const $scrollableElement = document.querySelector('.my-scrollable-element'); enablePageScroll($scrollableElement);
Returns the state of the page scroll bar.
import disablePageScroll, getScrollState > from 'scroll-lock'; console.log(getScrollState()); //true disablePageScroll(); console.log(getScrollState()); //false
import disablePageScroll, enablePageScroll, clearQueueScrollLocks, getScrollState > from 'scroll-lock'; disablePageScroll(); disablePageScroll(); disablePageScroll(); disablePageScroll(); enablePageScroll(); console.log(getScrollState()); //false clearQueueScrollLocks(); enablePageScroll(); console.log(getScrollState()); //true
Returns the width of the scroll bar.
import getPageScrollBarWidth > from 'scroll-lock'; document.body.style.overflow = 'scroll'; console.log(getPageScrollBarWidth()); //Number disablePageScroll(); console.log(getPageScrollBarWidth(true)); //Number document.body.style.overflow = 'hidden'; console.log(getPageScrollBarWidth()); //Number console.log(getPageScrollBarWidth(true)); //0
Returns the width of the scroll bar to specific moment.
import disablePageScroll, getCurrentPageScrollBarWidth > from 'scroll-lock'; console.log(getCurrentPageScrollBarWidth()); //Number disablePageScroll(); console.log(getCurrentPageScrollBarWidth()); //0
Makes elements with this selector scrollable.
- scrollableSelector — ( String | String array ) scrollable selector
Initial value: [‘[data-scroll-lock-scrollable]’]
import disablePageScroll, addScrollableSelector > from 'scroll-lock'; addScrollableSelector('.my-scrollable-selector'); disablePageScroll();
Makes elements with this selector not scrollable.
import removeScrollableSelector > from 'scroll-lock'; removeScrollableSelector('.my-scrollable-selector');
Makes the element scrollable.
import disablePageScroll, addScrollableTarget > from 'scroll-lock'; const $scrollableElement = document.querySelector('.my-scrollable-element'); addScrollableTarget($scrollableElement); disablePageScroll();
Makes the element not scrollable.
import removeScrollableTarget > from 'scroll-lock'; const $scrollableElement = document.querySelector('.my-scrollable-element'); removeScrollableTarget($scrollableElement);
Makes elements with this selector lockable.
- lockableSelector — ( String | String array ) lockable selector
Initial value: [‘[data-scroll-lock-lockable]’]
import disablePageScroll, addLockableSelector > from 'scroll-lock'; addLockableSelector('.my-lockable-selector'); disablePageScroll();
Makes the element lockable.
import disablePageScroll, addLockableTarget > from 'scroll-lock'; const $lockableElement = document.querySelector('.my-lockable-element'); addLockableTarget($lockableElement); disablePageScroll();
Fills the gap with elements with this selector.
- fillGapSelector — ( String | String array ) a fill gap selector
Initial value: [‘body’, ‘[data-scroll-lock-fill-gap]’]
import addFillGapSelector > from 'scroll-lock'; addFillGapSelector('.my-fill-gap-selector');
Returns the gap for elements with this selector.
import removeFillGapSelector > from 'scroll-lock'; removeFillGapSelector('.my-fill-gap-selector');
Fills the gap at the element.
import addFillGapTarget > from 'scroll-lock'; const $fillGapElement = document.querySelector('.my-fill-gap-element'); addScrollableTarget($fillGapElement);
Returns the gap at the element.
import removeFillGapTarget > from 'scroll-lock'; const $fillGapElement = document.querySelector('.my-fill-gap-element'); removeFillGapTarget($fillGapElement);
Changes the method of filling the gap.
- fillGapMethod — ( String: ‘padding’, ‘margin’, ‘width’, ‘max-width’, ‘none’ ) gap-filling method
Default value: padding
import setFillGapMethod > from 'scroll-lock'; setFillGapMethod('margin');
import refillGaps > from 'scroll-lock'; refillGaps();
🙌 🙌 I would like to thank “Armani” for the translation. 🙌 🙌
About
🔨 Cross-browser JavaScript library to disable scrolling page