Как предотвратить прокрутку полосы прокрутки от веб-страницы?

218

У меня есть веб-сайт с выравниванием по центру DIV. Теперь некоторые страницы нуждаются в прокрутке, некоторые нет. Когда я перемещаюсь от одного типа к другому, появление полосы прокрутки перемещает страницу на несколько пикселей в сторону. Есть ли способ избежать этого без явного отображения полос прокрутки на каждой странице?

Дмитрий Нестерук
источник
6
Почему никто не упоминает overflow-y: overlayв этой теме?
milkersarac
3
Согласно документам overflow-y: overlay
Mozilla

Ответы:

267

overflow-y: scroll - это правильно, но вы должны использовать его с тегом html, а не с body, иначе вы получите двойную полосу прокрутки в IE 7.
Поэтому правильный css будет:

html {
  overflow-y: scroll;
}
Ruben
источник
1
IE 10+ имеет плавающую полосу прокрутки, поэтому вы должны отключить это для этих браузеров
Ruben
1
это может вызвать такие проблемы, как двойная полоса прокрутки при использовании в сочетании с модальной загрузкой fancybox или twitter
Ruben
дополнительная информация: щебет-бутстрап теперь добавляет .modal-open к вашему телу, когда модал открыт
Ruben
55
Стоит отметить, что это постоянно показывает вертикальную полосу прокрутки. Может не всегда быть приемлемым.
rustyx
Я получаю двойную полосу прокрутки в Chromium и Firefox. Я использую flex-box; может быть, это является причиной ...
Гаррет
72

Оберните содержимое вашего прокручиваемого элемента в div и примените padding-left: calc(100vw - 100%);.

<body>
    <div style="padding-left: calc(100vw - 100%);">
        Some Content that is higher than the user's screen
    </div>
</body>

Хитрость в том, что 100vwпредставляет 100% области просмотра, включая полосу прокрутки. Если вы вычтите 100%, что является доступным пространством без полосы прокрутки, вы получите ширину полосы прокрутки или 0ее нет. Создание отступа такой ширины слева будет имитировать вторую полосу прокрутки, смещая центрированное содержимое назад вправо.

Обратите внимание, что это будет работать только в том случае, если прокручиваемый элемент использует всю ширину страницы, но в большинстве случаев это не должно быть проблемой, потому что есть только несколько других случаев, когда вы центрируете прокручиваемый контент.

Rapti
источник
1
Было бы лучше применять через класс, чем встроенный стиль, и будет работать только в этих браузерах , но это умная техника - я этого не осознавал 100vwи 100%измерял разные вещи, поэтому я узнал кое-что полезное из этого!
Ник Ф
21
Это абсолютно гениально и действительно лучший ответ, учитывая, что поддержка браузера для calc очень хорошая.
Майкл
1
Вы можете сделать то же самое, за исключением того, что вместо добавления поля слева вы добавляете отрицательное поле справа (см. Stackoverflow.com/a/39289453/6015444 ).
Touniouk
2
Это решение вызовет аналогичные проблемы с цветом фона, такие как ответ "width: calc (100vw - 34px);" но на левой стороне.
Мацей Лью
1
Я бы рекомендовал добавить несколько медиа-запросов к этому стилю @media screen and (min-width: 800px) {...} . В случаях, когда содержание будет соответствовать ширине страницы. Например, в небольших разрешениях будет ненужный пробел, сдвигая контент вправо
MarkosyanArtur
44

Думаю, нет. Но укладка bodyс overflow: scrollдолжны делать. Вы, кажется, знаете это, хотя.

Михаил Крелин - хакер
источник
3
Звучит хорошо ... заставить страницу всегда показывать полосу прокрутки, нужна она ей или нет, ... тогда между типами страниц нет визуальных изменений.
Eidylon
1
Да, но IIRC, это показывает обе полосы прокрутки. Мне действительно не нужен горизонтальный.
Дмитрий Нестерук
Это правда. Но я мало что могу сделать, чтобы помочь вам :( На самом деле, я считаю, что только первое предложение моего ответа является реальным ответом на этот вопрос.
Майкл Крелин - хакер
49
overflow-y: scroll:)
Свиш
2
Вот лучший ответ
Сами
36

С прокруткой всегда отображается, может быть, не очень хорошо для макета.

Попробуйте ограничить ширину тела с помощью css3

body {
    width: calc(100vw - 34px);
}

vwявляется шириной области просмотра (см. эту ссылку для некоторых объяснений),
calcрассчитанной в css3
34pxдля двойной ширины полосы прокрутки (см. это для фиксированных значений или для расчета, если вы не доверяете фиксированным размерам)

Moesio
источник
4
Все бесполезно, пока кому-то не нужно.
Мезио
3
Это визуально гораздо менее навязчиво, чем просто нажимать полосы прокрутки, как описывает принятый ответ.
Сайлас Хансен
4
Пока это работает лучше всего для моих нужд, я также добавил, padding-left: 34px;чтобы равномерно центрировать мою страницу.
Пэт Мильяччио
3
Это должен быть принятый ответ, в отличие от принятого в настоящее время, он фактически отвечает на вопрос!
Coz
2
Это вызовет проблемы, если у вас есть панель навигации / заголовок с другим цветом, чем фон тела или нижняя граница и т. Д.
Зия Уль Рехман Могол
28
html {
  overflow-x: hidden;
  margin-right: calc(-1 * (100vw - 100%));
}

Пример . Нажмите кнопку «Изменить минимальную высоту».

С помощью calc(100vw - 100%)мы можем вычислить ширину полосы прокрутки (и если она не отображается, она будет 0). Идея: используя отрицательное поле справа, мы можем увеличить ширину <html>до этой ширины. Вы увидите горизонтальную полосу прокрутки - ее следует скрыть, используя overflow-x: hidden.

орангутанг
источник
Мне пришлось поместить тело в div и применить поле к div, чтобы оно работало (похоже на ответ Рапти ). Но это выглядит намного аккуратнее.
Touniouk
1
Это прекрасно работает и не приводит к нежелательным горизонтальным полосам прокрутки в Chrome или Firefox. Почему бы просто не использовать calc(100% - 100vw)вместо умножения на -1?
SystemParadox
13

Я не знаю, старый ли это пост, но у меня была та же проблема, и если вы хотите прокручивать только по вертикали, попробуйте overflow-y:scroll


источник
13

Если при изменении размера или после загрузки некоторых данных добавляется полоса прокрутки, вы можете попробовать выполнить следующее, создать класс и применить этот класс.

.auto-scroll {
   overflow-y: overlay;
   overflow-x: overlay;
}
kunalkamble
источник
3

Я решил проблему на одном из своих сайтов, явно установив ширину тела в javascript размером окна просмотра за вычетом ширины полосы прокрутки. Я использую описанную здесь функцию на основе jQuery для определения ширины полосы прокрутки.

<body id="bodyid>

var bodyid = document.getElementById('bodyid');
bodyid.style.width = window.innerWidth - scrollbarWidth() + "px";
Фрэнк Л
источник
10
Я даже не могу объяснить, почему это такая плохая практика.
Мифофешелон
20
@BenHooper: Я хотел бы знать, почему это плохая практика.
Саад
1
Что произойдет, если вы измените размер окна?
Брейден Steffaniak
3

Расширяя ответ, используя это:

body {
    width: calc(100vw - 17px);
}

Один комментатор предложил также добавить левый отступ, чтобы сохранить центрирование:

body {
    padding-left: 17px;
    width: calc(100vw - 17px);
}

Но тогда все выглядит не правильно, если ваш контент шире, чем область просмотра. Чтобы это исправить, вы можете использовать медиа-запросы, например:

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

Где 1058px = ширина содержимого + 17 * 2

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

Грег Сент-Онж
источник
3

Расширение ответа Rapti , это должно работать точно так же, но оно добавляет больше поля к правой стороне bodyи скрывает его с отрицательным htmlполем вместо добавления дополнительного отступа, который потенциально может повлиять на макет страницы. Таким образом, на реальной странице ничего не меняется (в большинстве случаев), и код все еще функционирует.

html {
    margin-right: calc(100% - 100vw);
}
body {
    margin-right: calc(100vw - 100%);
}
Грант Гричан
источник
Я обнаружил, что в Chrome это добавляет горизонтальную прокрутку на страницах с вертикальной полосой прокрутки на моем сайте начальной загрузки.
Рыжая белка
Вы пытались выяснить, почему? Проверьте инспектор элементов и посмотрите, не перегружен ли Bootstrap полями, полосами прокрутки или чем-то подобным.
Грант Гричан
1
Вероятно, это было связано с полями в 15px, которые Bootstrap накладывает на все: при проверке страницы поле контейнера попадает под полосу прокрутки. Я применил, overflow-x: hiddenи это исправило.
Рыжая Белка
3

Решение @ kashesandr помогло мне, но чтобы скрыть горизонтальную полосу прокрутки, я добавил еще один стиль для тела. вот полное решение:

CSS

<style>
/* prevent layout shifting and hide horizontal scroll */
html {
  width: 100vw;
}
body {
  overflow-x: hidden;
}
</style>

JS

$(function(){
    /**
     * For multiple modals.
     * Enables scrolling of 1st modal when 2nd modal is closed.
     */
    $('.modal').on('hidden.bs.modal', function (event) {
      if ($('.modal:visible').length) {
        $('body').addClass('modal-open');
      }
    });
});

Решение JS Only (когда 2-й модал открывается из 1-го модала):

/**
 * For multiple modals.
 * Enables scrolling of 1st modal when 2nd modal is closed.
 */
$('.modal').on('hidden.bs.modal', function (event) {
  if ($('.modal:visible').length) {
    $('body').addClass('modal-open');
    $('body').css('padding-right', 17);
  }
});
Хасан Тарек
источник
2

Я пытался исправить, вероятно, ту же проблему, которая была вызвана .modal-openклассом начальной загрузки Twitter body. Решение html {overflow-y: scroll}не помогает. Одно из возможных решений я нашел , чтобы добавить {width: 100%; width: 100vw}к htmlэлементу.

kashesandr
источник
1
или измените его на body {overflow-y: scroll}
Рубен
1
Но это всегда будет отображать полосу прокрутки, даже если это не требуется.
Rapti
Вы должны объяснить, почему вы устанавливаете ширину в два раза? html { width: 100vw; }работал на меня
Хасан Тарек
Для меня это фактически создает две полосы прокрутки
rbansal
2

Я использую, чтобы иметь эту проблему, но самый простой способ исправить это (это работает для меня):

на тип файла CSS:

body{overflow-y:scroll;}

как это просто! :)

Мелвин Герреро
источник
2

Решения, опубликованные с использованием calc (100vw - 100%), находятся на правильном пути, но есть проблема с этим: у вас навсегда останется поле слева от размера полосы прокрутки, даже если вы измените размер окна так, чтобы содержимое заполняет весь видовой экран.

Если вы попытаетесь обойти это с помощью медиа-запроса, у вас будет неловкий момент щелчка, потому что поле не будет постепенно уменьшаться при изменении размера окна.

Вот решение, которое обходит это, и у AFAIK нет недостатков:

Вместо того чтобы использовать margin: auto для центрирования вашего контента, используйте это:

body {
margin-left: calc(50vw - 500px);
}

Замените 500 пикселей на половину максимальной ширины вашего контента (поэтому в этом примере максимальная ширина контента составляет 1000 пикселей). Контент теперь будет оставаться в центре, а поле будет постепенно уменьшаться до тех пор, пока контент не заполнит область просмотра.

Чтобы препятствовать тому, чтобы отступ становился отрицательным, когда область просмотра меньше, чем max-width, просто добавьте медиа-запрос следующим образом:

@media screen and (max-width:1000px) {
    body {
        margin-left: 0;
    }
}

И вуаля!

Джонатан С.И.
источник
2

Если ширина таблицы не изменится, вы можете установить ширину элемента (такого как tbody), который содержит полосу прокрутки> 100% (оставляя дополнительное пространство для полосы прокрутки), и установить для overflow-y значение «overlay» (так что полоса прокрутки остается фиксированной и не будет сдвигать таблицу влево, когда она появится). Также установите фиксированную высоту для элемента с полосой прокрутки, чтобы полоса прокрутки появлялась при превышении высоты. Вот так:

tbody {
  height: 100px;
  overflow-y: overlay;
  width: 105%
}

Примечание: вам придется вручную отрегулировать ширину%, так как% пространства, занимаемого полосой прокрутки, будет зависеть от ширины вашей таблицы (то есть: меньшая ширина таблицы, больше% требуется для размещения полосы прокрутки, так как ее размер в пикселях постоянен )

Пример динамической таблицы:

function addRow(tableID)
{
    var table = document.getElementById(tableID);
    var rowCount = table.rows.length;
    var row = table.insertRow(rowCount);
    var colCount = table.rows[0].cells.length;
  
    for(var i=0; i<colCount; i++)
    {
        var newRow = row.insertCell(i);

        newRow.innerHTML = table.rows[0].cells[i].innerHTML;
        newRow.childNodes[0].value = "";
    }
}
 
function deleteRow(row)
{
    var table = document.getElementById("data");
    var rowCount = table.rows.length;
    var rowIndex = row.parentNode.parentNode.rowIndex;

    document.getElementById("data").deleteRow(rowIndex);
}
.scroll-table {
  border-collapse: collapse;
}

.scroll-table tbody {
  display:block;
  overflow-y:overlay;
  height:60px;
  width: 105%
}

.scroll-table tbody td {
  color: #333;
  padding: 10px;
  text-shadow: 1px 1px 1px #fff;
}

.scroll-table thead tr {
  display:block;
}

.scroll-table td {
    border-top: thin solid; 
    border-bottom: thin solid;
}

.scroll-table td:first-child {
    border-left: thin solid;
}

.scroll-table td:last-child {
    border-right: thin solid;
}

.scroll-table tr:first-child {
    display: none;
}

.delete_button {
    background-color: red;
    color: white;
}

.container {
  display: inline-block;
}

body {
  text-align: center;
}
<!DOCTYPE html>
<html lang="en">
<head>
  <link rel="stylesheet" href="test_table.css">
</head>

<body>
<h1>Dynamic Table</h1>
<div class="container">

  <table id="data" class="scroll-table">
    <tbody>
      <tr>
        <td><input type="text" /></td>
        <td><input type="text" /></td>
        <td><input type="button" class="delete_button" value="X" onclick="deleteRow(this)"></td>
      </tr>
    </tbody>
  </table>

  <input type="button" value="Add" onclick="addRow('data')" />

</div>

<script src="test_table.js"></script>
</body>
</html>

Роберт Джеймс Миета
источник
1

Просто установив ширину вашего элемента контейнера, как это сделает свое дело

width: 100vw;

Это заставит этот элемент игнорировать полосу прокрутки, и он будет работать с цветом фона или изображений.

Barsonax
источник
-3

Я использовал JQuery, чтобы решить эту проблему

$('html').css({
    'overflow-y': 'hidden'
});

$(document).ready(function(){
  $(window).load(function() {
    $('html').css({
      'overflow-y': ''
    });
  });
});
Уилл Макмилиан
источник
3
Вы, вероятно, получите плохой ответ на ваш ответ, потому что для этого решения требуется вся структура JavaScript. "JQuery все вещи!"
Пол Ламмерцма
3
да, jQuery - это определенно верный
Анонимный
-4
@media screen and (min-width: 1024px){
    body {
    min-height: 700px
    }
}
Vicky
источник
Добро пожаловать в стек переполнения! Хотя этот фрагмент кода может решить вопрос, в том числе объяснение действительно помогает улучшить качество вашего сообщения. Помните, что вы отвечаете на вопрос читателей в будущем, и эти люди могут не знать причин, по которым вы предлагаете код. Также постарайтесь не переполнять ваш код пояснительными комментариями, это снижает удобочитаемость кода и пояснений!
Эндрю Майерс
-5

Вопреки принятому ответу, который предлагает постоянную полосу прокрутки в окне браузера, даже если содержимое не выходит за пределы экрана , я бы предпочел использовать:

html{
  height:101%;
}

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

Это имеет больше смысла, чем это .

Никунь Мадогария
источник
1
По крайней мере, последнее предложение неверно в вашем ответе. Это имеет смысл аналогично избыточной пустой странице, напечатанной на принтере.
vp_arth