Skip to content

Instantly share code, notes, and snippets.

@barneycarroll
Last active August 29, 2022 12:02
Show Gist options
  • Star 93 You must be signed in to star a gist
  • Fork 21 You must be signed in to fork a gist
  • Save barneycarroll/6550066 to your computer and use it in GitHub Desktop.
Save barneycarroll/6550066 to your computer and use it in GitHub Desktop.
Lock and unlock a page's scroll position.

jquery.scrollLock.js

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 );
$.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', $( '<x>' ).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();
}
}
};
}() );
$.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();
}
}
};
}() );
@webmaster-jhon
Copy link

Thanks for this file. I downloaded jquery.scrollLock.js but $.scrollLock(true) not working properly on my page. When i call this function scroll bar remains same i.e. still scroll able.

@RyKilleen
Copy link

Thank you, worked flawlessly. I needed to modify from scroll to hidden and feared having to tinker, but you had clearly prepared for that scenario. Very much appreciated.

@dsandstrom
Copy link

Thanks for this. Unfortunately the simple version does not work well on iOS. The page still scrolls underneath my overlay, overflow: hidden doesn't perform the same on Apple devices. I can't find documentation of this (go figure), but here is the fix I was using. However, when I use that CSS, the page scrolls to the top. Yet, the original version seems to work fine and locks the body scroll position in place.

@ahmednooor
Copy link

hi i am a novice and just know html and css a lil bit. i tried some solutions on the web but couldnt figure out how to tweak them according to my project and i hope this may work as it is not specified to some predefined classes. so could you plz tell the procedure to use it? like,

  1. where should i put the calling function?
  2. would i have to link to the jquery library in head too? or it will work on its own?
  3. if i have to put in my project specific class or id if it requires where should i put it?

for example i have a class .overlay which is hidden by default and when i click on on an anchor tag which is targeted to a div having the class .overlay and an id to get targeted and a modal opens i want to disable the body from scrolling when modal is opened.

sorry for asking an annoying question.

@jazcam
Copy link

jazcam commented Mar 29, 2016

Nice. Well done. Took a bit of doing, but between here and your demo on jsfiddle, I figured it out and have it working.

@xizon
Copy link

xizon commented Apr 24, 2016

Thanks!

@sanketj14
Copy link

You sir, are my hero! you can't imagine just how much of my efforts are saved with this wonderful library. worked right off the bat! Thanks, keep up the good work!

@mrlaseptima
Copy link

hey men thank you

@m11z
Copy link

m11z commented Feb 9, 2017

Thanks!

@tscrady
Copy link

tscrady commented Apr 19, 2017

Thank you very much, works on ios10, Firefox 51.0.1, Chrome Version 56.0.2924.87

@jessevdp
Copy link

👍

@mhshakouri
Copy link

this is a great tool I really recommend it
Thanks

@nitin00709
Copy link

Thanks a lot for this wonderful library. It worked flawlessly. I had been trying for so long to hide scrolling on body while a pop-up window appears on ios, you have saved a lot of my time. Very much appreciated. I really recommend it. For those who are dealing with such issue I really recommend you to use this one it works on ios devices too.

@Dylan-Harrington
Copy link

Dylan-Harrington commented Feb 13, 2018

This is incredible. Multiple days of searching for an answer and trying a thousand different things finally concluded thanks to this little library. I hope everyone grinding their teeth over this issue finds it soon. Thank you SO much!

@leonardoervilha
Copy link

Thanks brother , God bless you

@techlemur
Copy link

Thank you! Works perfectly except for an occasional error with "styleAttr.split". Easily fixed by changing line 33 to the following:
try { styleStrs = styleAttr.split(/;\s/); } catch (err) { return; }

@hiddebijnerds
Copy link

Works perfectly 👍

@StrangerPings
Copy link

Thank you for this! 😃

@nilay255
Copy link

nilay255 commented May 2, 2018

How do I check if the scrollLock is active or not for jquery.scrollLock.js? Like how do I check the locked status is true or false. @barneycarroll

@rajakhoury
Copy link

Thanks alot for sharing

@BeholdPL
Copy link

BeholdPL commented Nov 20, 2018

Works great! But when scroll is locked, then every position: fixed elements on site are disappear. Is there possibility to avoid that?

@locopump
Copy link

Do you have any example of use of this code ??

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment