Как сделать чтобы страница не дергалась? Когда убираем скроллбар?
Проблема такая, что когда открывается модальное окно, то используется правило overflow: hidden; чтобы отключить прокрутку. Это вызывает скрытие скроллбара, на виндовых устройствах скроллбар фиксированный когда исчезает дергает контент. Помогите советом как решить данный баг.
.popup{
position: fixed;
top: 0;
left: 0;
height: 100vh;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
visibility: hidden;
z-index: 100;
}
.js-blockScroll{
overflow-y: hidden;
/*padding-right: 20px;*/
/*width: auto;*/
}
Ответы (1 шт):
Есть два решения этой проблемы:
1. Динамический сдвиг на ширину полосы прокрутки.
Для этого нужно динамически определять ширину прокрутки. У элемента html изначально должно быть overflow-y: scroll. Перед открытием модального окна, элементу html задается overflow: hidden, а элементу body задается margin-right: (ширина полосы прокрутки)px (при этом у обоих элементов не должны быть заданы ширины width). Далее запускается слушатель события window resize, и при масштабировании окна, динамически корректируется margin-right: (ширина полосы прокрутки)px у элемента body.
При скрытии модального окна отключается слушатель window resize, убираются margin у body и overflow у html.
Ширину вертикальной и горизональной полосы прокрутки обычно определяют с помощью такой функции:
var getScrollBarSize = (function() {
var el = window.document.createElement('textarea'), style = {
'visibility': 'hidden', 'position': 'absolute', 'zIndex': '-2147483647',
'top': '-1000px', 'left': '-1000px', 'width': '1000px', 'height': '1000px',
'overflow': 'scroll', 'margin': '0', 'border': '0', 'padding': '0'
}, support = el.clientWidth !== undefined && el.offsetWidth !== undefined;
for (var key in style) {
if (style.hasOwnProperty(key)) {
el.style[key] = style[key];
}
}
return function() {
var size = null;
if (support && window.document.body) {
window.document.body.appendChild(el);
size = [el.offsetWidth - el.clientWidth, el.offsetHeight - el.clientHeight];
window.document.body.removeChild(el);
}
return size;
};
})();
console.log(getScrollBarSize());
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
У этого способа есть несколько особенностей. Правильная реализация должна учитывать направление контента dir="ltr" или dir="rtl". Сдвигать придется не только body, но и все элементы, имеющие position: fixed позиционированные от той стороны с которой находится прокрутка. Последние версии браузера IE имеют баг с масштабированием полос прокруток (полосы прокрутки окна браузера и элементов имеют разную ширину, что не дает правильно определить ширину прокрутки).
2. Верстка слоями.
Создается глобальный элемент div id="wrapper", и глобальный скролл переносится в него, а у элементов html, body - отключается:
html, body {
height: 100%;
overflow: hidden;
}
html > body > #wrapper {
height: 100%;
position: relative;
overflow: auto;
}
Все модальные окна, при этом, также размещаются внутри body, на одном уровне с элементом #wrapper. Тогда у вас вообще не будет проблем с полосами прокруток, так как у каждого слоя они будут свои. Но у этого способа есть несколько особенностей... В мобильных браузерах перестает скрываться панель инструментов браузера. Вместо position: fixed вы везде должны как-то обходится с помощью position: absolute, что иногда совсем не "гибко". Вам нужно также задать @media print стили для корректной печати такого сайта.