Как остановить мой веб-контент с помощью сдвига влево при появлении вертикальной полосы прокрутки? Сводная информация о совете 2017

Многие программисты спросили, как остановить их содержимое веб-страницы — особенно их центрированное содержимое веб-страницы (margin: 0 auto;) — от сдвига (сдвигается) горизонтально, когда появляется вертикальная полоса прокрутки. & ensp; Это была постоянная проблема для пользователей Ajax и таких людей, как я, которые используют скрытые div и вкладки для организации данных.

Проблема возникает, когда текущая отображаемая страница изменяется так, что высота отображаемого материала (высота внутреннего окна) резко превышает высоту физического окна.

Проблема усугубляется тем, что все полосы прокрутки не созданы равными. & ensp; Различные браузеры дают свои полосы прокрутки разной ширины, и эта разница не может (или, по крайней мере, не должна) быть предсказана. & ensp. Короче говоря, идеальное решение - независимая ширина полосы прокрутки.

Таким образом, это вопрос с автоответчиком, который отсылает все эти ответы с комментариями по их полезности (где это возможно) вместе с моим собственным решением в один ответ по состоянию на 5 августа 2017. & ensp; Я отмечен как дублирует многие из предыдущих вопросов, которые я могу найти, чтобы люди могли найти исчерпывающее обсуждение проблемы.

Обратите внимание, что в этом ответе рассматриваются проблемы с перемещением содержимого BODY. & ensp. Если у вас есть DIV с фиксированной высотой, которая имеет проблемы с переключением, вы должны установить ширину DIV на фиксированную (px) ширину, чтобы ее плавающие полосы прокрутки над текстом и добавьте правое дополнение, чтобы текст не падал под ним. Авторы: Hashbrown, Avrahamcool, Эдвард Ньюсом

Ответ 1

Прежде чем перейти к отдельным решениям, следует упомянуть, что они разбиваются на три категории: CSS-, CSS3- и Javascript-решения.

Решения CSS, как правило, ребристые, но очень предсказуемые и очень хорошо поддерживаемые.

В решениях CSS3 есть затраты на расчет процессора, такие как Javascript, но их легко реализовать. & ensp; Однако в годы, предшествовавшие 2017 году, они имели спорадическую поддержку в браузерах. & ensp; Это улучшается с течением времени. & ensp; В конечном счете, они скорее всего, будет лучшим решением, но мои собственные исследования сегодня продемонстрировали, что поддержка просто недостаточно согласована, и, кроме того, унаследованная поддержка браузера отсутствует.

Решения Javascript (будь то в прямом Javascript или в jQuery) нуждаются в дополнительном кодировании, чтобы сделать их надежными, поскольку у них нет внутренней поддержки (например, изменения размера окна). Однако они являются наиболее предсказуемыми и наиболее обратными в то же время сохраняя эстетику страницы. & ensp; я считаю, что линия для устаревших браузеров находится между IE6 и IE7. И, честно говоря, мои соболезнования всем, кто по-прежнему использует старый браузер.

Обратите внимание, что я не не включил каждое решение CSS3 и Javascript, ранее отправленное в Stack Exchange. & ensp; Некоторые, хотя и были романа, имели существенные недостатки и поэтому не были включены здесь.


Решение №1: Решение для CSS

Авторы: Hive7, koningdavid, Кристофер Элиассон, Алекское ущелье, Скотт Бартель, Шон Тейлор, mVChr, fsn, Damb, Sparky, Рубен, Майкл Крелин - хакер, Мелвин Герреро

Принудительно включить панель прокрутки.

<style>
html {
    overflow-y: scroll;
}
</style>

Это решение в основном гарантировано всегда работает (есть некоторые исключения, но они очень редки), но это эстетически неудобно. & ensp; Полоса прокрутки всегда будет видна, нужна ли она или нет. & ensp; заключается в использовании этого решения в теге html, некоторые предлагают его использовать в теге body.

Последствия

Microsoft (IE10 +) имеет встроенные плавающие полосы прокрутки, что означает, что ваша страница не может быть сосредоточена в ней, как это было бы в других браузерах. & ensp. Однако это кажется очень незначительной проблемой.

При использовании структурированных интерфейсов, таких как FancyBox, Flex-Box или Twitter Bootstrap Modal, это может привести к появлению двойной полосы прокрутки, поскольку эти интерфейсы создают свои собственные полосы прокрутки.

Программистам следует избегать использования overflow: scroll, поскольку это приведет к появлению как вертикальной, так и горизонтальной полос прокрутки.

Решение # 1a: Альтернатива

Авторы: koningdavid, Nikunj Madhogaria

Умная альтернатива, но имеющая только незначительную эстетическую разницу, заключается в следующем:

<style>
html {
    height: 101%;
}
</style>

Это активирует фон полосы прокрутки, но не активирует вкладку полосы прокрутки, если только ваш вертикальный контент не переполняет нижний край окна. & ensp. Тем не менее, он имеет ту же самую слабость, что пространство полосы прокрутки постоянно потребляется независимо от того, или нет.

Решение № 1b: более современное решение

Авторы: Кайл Думович, SimonDos

Браузеры начинают использовать значение overlay для полос прокрутки, имитируя плавающую полосу прокрутки IE10 +.

<style>
html {
    overflow-y: overlay;
}
</style>

Это решение подражает плавающей полосе прокрутки в IE10 +, но пока не доступно во всех браузерах и все еще имеет некоторые особенности реализации. & ensp. Это решение, как известно, не работает в таких инфраструктурных средах, как Bootstrap Modal.


Решение №2: решение CSS3

Использовать CSS3 для расчета ширины. & ensp; Существует множество способов сделать это с преимуществами и недостатками для каждого. Основные недостатки связаны с тем, что (а) не знает фактическую ширину полосы прокрутки, (б), касающуюся изменения размера экрана, и (c) тот факт, что CSS постепенно становится еще-еще-полностью функционирующим языком программирования -— как Javascript — но еще не полностью превратилась в таковую. Независимо от того, имеет ли смысл, чтобы это стало таковым, это дискуссия по другому вопросу.

Аргумент, что пользователи могут отключить Javascript, поэтому предпочтительным решением для CSS является неуместное. & ensp; Программирование на стороне клиента стало настолько распространенным, что только самые параноидальные люди все еще отключили Javascript. & ensp; Лично я больше не считайте это обоснованным аргументом.

Следует отметить, что некоторые решения изменяют margin, а другие изменяют padding. & ensp; Те, которые изменяют margin, имеют общую проблему: если у вас есть панели навигации, заголовки, границы и т.д., которые используют разные цвет, чем фон страницы, это решение будет вызывать нежелательные границы. & ensp; Вероятно, любое решение, использующее margin, может быть повторно спроектировано для использования padding и наоборот.

Решение # 2a: решение на основе HTML

Авторы: TranslucentCloud, Михаил Малостанидис

<style>
html {
    margin-left: calc(100vw - 100%);
    margin-right: 0;
}
</script>

Решение №2b: решение на основе BODY

Авторы: Greg St.Onge, Moesio, Джонатан С.И.

<style>
body {
    padding-left: 17px;
    width: calc(100vw - 17px);
}
@media screen and (min-width: 1058px) {
    body {
        padding-left: 17px;
        width: calc(100vw - 17px);
    }
}
</style>

100vw составляет 100% ширины окна просмотра.

Последствия

Некоторые пользователи предположили, что это решение создает нежелательный шум экрана при изменении размера окна (возможно, процесс вычисления происходит несколько раз во время процесса изменения размера). Возможное обходное решение заключается в том, чтобы избежать использования margin: 0 auto; для центра вашего контента и вместо этого используйте следующее (1000px и 500px, показанные в этом примере, представляют максимальную ширину вашего содержимого и половину этой суммы):

<style>
body {
    margin-left: calc(50vw - 500px);
}
@media screen and (max-width: 1000px) {
    body {
        margin-left: 0;
    }
}
</style>

Это решение с фиксированной шириной полосы прокрутки, которое не зависит от браузера. & ensp. Чтобы сделать его независимым от браузера, вы должны включить Javascript для определения ширины полос прокрутки. & ensp; Пример, который вычисляет ширину, но делает не повторное включение значения:

Обратите внимание, что нижеприведенный фрагмент кода неоднократно размещался в Stack Exchange и других местах в Интернете, без каких-либо твердых атрибутов.

function scrollbarWidth() {
    var div = $('<div style="width:50px;height:50px;overflow:hidden;position:absolute;top:-200px;left:-200px;"><div style="height:100px;"></div>');
    // Append our div, do our calculation and then remove it
    $('body').append(div);
    var w1 = $('div', div).innerWidth();
    div.css('overflow-y', 'scroll');
    var w2 = $('div', div).innerWidth();
    $(div).remove();
    return (w1 - w2);
}

Решение №2c: решение на основе DIV

Авторы: Rapti

Используйте вычисления CSS3, применяемые непосредственно к элементу DIV контейнера.

<body>
    <div style="padding-left: calc(100vw - 100%);">
    My Content
    </div>
</body>

Последствия

Как и все решения CSS3, это не поддерживается всеми браузерами. & ensp; Даже те браузеры, которые поддерживают вычисления в видовом экране, не имеют (на момент написания этой статьи) его произвольное использование.

Решение №2d: Модификация Bootstrap

Авторы: Михаил Малостанидис, kashesandr

Пользователи Twitter Bootstrap Modal нашли полезным применить следующий CSS3 к своему элементу HTML.

<style>
html {
    width: 100%;
    width: 100vw;
}
</style>

Другое предложение - создать оболочку вокруг вашей оболочки содержимого, которая используется для автоматического обнаружения изменений в ширине окна просмотра.

<style>
body {
    overflow-x: hidden;
}
#wrap-wrap {
    width: 100vw;
}
#content-wrap {
    margin: 0 auto;
    width: 800px;
}
</style>

Я не пробовал ни одного из них, поскольку я не использую Bootstrap.


Решение №3: Решение Javascript

Авторы: Sam, JBH

Это мое любимое решение, поскольку оно касается всех проблем и разумно обратно совместимо с устаревшими браузерами. & ensp; Лучше всего, это независимость от ширины полосы прокрутки.

<script>
function updateWindow(){
    document.body.style.paddingLeft = (window.innerWidth - document.body.clientWidth);
    document.body.onclick=function(){
            document.body.style.paddingLeft = (window.innerWidth - document.body.clientWidth);
    }
}
window.onload=updateWindow();
window.addEventListener("resize", updateWindow());
updateWindow();
</script>

Последствия

Последняя команда updateWindow(); должна произойти непосредственно перед тегом </body>, чтобы избежать проблем с динамически загружаемым контентом, таким как Facebook Like-Boxes. & ensp; Казалось бы, он избыточен для события window.onload, но не каждый браузер рассматривает onload таким же образом. & ensp; Некоторые ждут асинхронных событий. & ensp; Другие не делают.

Функция выполняется каждый раз, когда пользователь нажимает на веб-страницу. И, наконец, современные компьютеры достаточно быстры, чтобы это не было проблемой. & ensp; Still & hellip;.

Наконец, функция должна быть выполнена после любого асинхронного обновления div (AJAX). & ensp; Это не показано в этом примере, но будет частью состояния готовности. & ensp. Например:

xmlhttp.onreadystatechange=function(){
    if(xmlhttp.readyState==4 && xmlhttp.status==200){
        if(xmlhttp.responseText == 'false'){
            //Error processing here
        } else {
            //Success processing here
            updateWindow();
        }
    }
}

Решение № 3a: Измерение ширины полосы прокрутки

Авторы: Lwyrn

Это менее ценное решение, требующее времени для измерения ширины полосы прокрутки.

<script>
var checkScrollBars = function(){
    var b = $('body');
    var normalw = 0;
    var scrollw = 0;
    if(b.prop('scrollHeight')>b.height()){
        normalw = window.innerWidth;
        scrollw = normalw - b.width();
        $('#container').css({marginRight:'-'+scrollw+'px'});
    }
}
</script>
<style>
body {
    overflow-x: hidden;
}
</style>

Последствия

Как и другие решения, этот постоянно отключает горизонтальную полосу прокрутки.