在实现弹窗成果时通常咱们都不心愿浏览器还能持续滚动,特地是当弹窗里也有滚动条的时候,有双层滚动条的成果及体验都是极差的。
锁定页面的原理:
- 设置
<body>
标签的款式为overflow: hidden
- 给
<body>
标签增加一个值为滚动条宽度的padding-right
代码实现:
function lockScroll () { let body = document.body; // 记录了锁定滚动条之前body的属性,以便在解锁后复原锁定前的款式 let originBodyOverflow = body.style.overflow; let originBodyPaddingRight = body.style.paddingRight; let originBodyPaddingBottom = body.style.paddingBottom; let originBodyHasLockClass = body.classList.contains('bs-lock-scroll'); let hasScroll = hasScroll(); let scrollWidth = scrollWidth(); // 标记本次是否锁定了页面 let locked = false; if (!originBodyHasLockClass) { body.classList.add('bs-lock-scroll'); } if (originBodyOverflow != 'hidden') { body.style.overflow = 'hidden'; locked = true; if (hasScroll.vertical) { body.style.paddingRight = scrollWidth.vertical + 'px'; } if (hasScroll.horizontal) { body.style.paddingBottom = scrollWidth.horizontal + 'px'; } } // 返回一个解除锁定滚动条的函数 return function () { let body = document.body; if (!originBodyHasLockClass) { body.classList.remove('bs-lock-scroll'); } if (!locked) { return; } if (originBodyOverflow) { body.style.overflow = originBodyOverflow; } else { body.style.overflow = ''; // 移除body上的overflow属性 } if (originBodyPaddingRight && parseFloat(originBodyPaddingRight) !== scrollWidth.vertical) { body.style.paddingRight = originBodyPaddingRight; } else { body.style.paddingRight = ''; // 移除body上的paddingRight属性 } if (originBodyPaddingBottom && parseFloat(originBodyPaddingBottom) !== scrollWidth.horizontal) { body.style.paddingBottom = originBodyPaddingBottom; } else { body.style.paddingBottom = ''; // 移除body上的paddingBottom属性 } };};/** * 获取元素或浏览器滚动条的宽高 * @param ele dom元素 * @returns {{horizontal: number, vertical: number}} */function scrollWidth (ele) { var tempDiv; var tempInnerDiv = document.createElement('div'); var result = { vertical: 0, horizontal: 0 }; tempInnerDiv.style.cssText = 'width: 200px;height: 200px'; if (!ele || ele.nodeType != 1) { // 未传递dom元素则获取浏览器的滚动条 result.vertical = window.innerWidth - document.documentElement.offsetWidth; result.horizontal = window.innerHeight - document.documentElement.clientHeight; return result; } tempDiv = ele.cloneNode(true); tempDiv.style.cssText = 'width: 100px;height: 100px;opacity: 0;position:absolute;left: -100px;overflow:auto;'; tempDiv.appendChild(tempInnerDiv); document.body.appendChild(tempDiv); result.vertical = tempDiv.offsetWidth - tempDiv.clientWidth; result.horizontal = tempDiv.offsetHeight - tempDiv.clientHeight; document.body.removeChild(tempDiv); tempDiv = tempInnerDiv = null; return result;}/*** 判断浏览器或dom元素是否有滚动条* @returns {{horizontal: boolean, vertical: boolean}}*/function hasScroll () { return { vertical: document.body.scrollHeight > window.innerHeight, horizontal: document.body.scrollWidth > window.innerWidth };}
应用:
var unLock = lockScroll();// 解锁// unLock();
成果(屡次调用锁定):