Як запобігти перестановці веб-сторінки на смузі прокрутки?


218

У мене є веб-сайт з DIV, орієнтованим на центр. Тепер деякі сторінки потребують прокрутки, а деякі - ні. Коли я переходжу від одного типу до іншого, поява смуги прокрутки переміщує сторінку на кілька пікселів убік. Чи є спосіб уникнути цього, не чітко показуючи смуги прокрутки на кожній сторінці?


6
Чому ніхто не згадує про overflow-y: overlayцю тему?
milkersarac

3
Згідно з документами mozilla, overflow-y: overlayзнецінюється: developer.mozilla.org/en-US/docs/Web/CSS/overflow
drojf

Відповіді:


266

overflow-y: прокрутка правильна, але ви повинні використовувати її з html-тегом, а не body, інакше ви отримаєте подвійну панель прокрутки в IE 7.
Отже, правильним css було б:

html {
  overflow-y: scroll;
}

1
IE 10+ має плаваючу панель прокрутки, тому вам слід вимкнути це для цих браузерів
Рубен

1
це може спричинити такі проблеми, як подвійні смуги прокрутки при використанні в поєднанні з fancybox або twitter boalstrap modal
Рубен

додаткова інформація: twitter bootstrap тепер додає .modal-open до вашого тіла, коли модальний режим відкрито
Ruben

55
Варто зазначити, що це постійно показує вертикальну смугу прокрутки. Не завжди може бути прийнятним.
іржа

Я отримую подвійну смугу прокрутки як у Chromium, так і в Firefox. Я використовую flex-box; можливо, це спричиняє це ...
Гаррет

72

Загорніть вміст елемента, який прокручується, у розділ і застосуйте 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якщо її немає. Створення накладки такої ширини зліва буде імітувати другу смугу прокрутки, зсуваючи вміст, орієнтований по центру назад, вправо.

Зверніть увагу, що це спрацює лише в тому випадку, якщо елемент, який прокручується, використовує всю ширину сторінки, але це не повинно бути проблемою протягом більшої частини часу, оскільки є лише кілька інших випадків, коли ви зосереджуєте вміст, який прокручується.


1
Краще застосувати через клас, ніж стиль вбудованого, і він працюватиме лише в цих браузерах , але це розумна техніка - я цього не усвідомлював 100vwі не 100%міряв різні речі, тому з цього я навчився чогось корисного!
Нік Ф

21
Це абсолютно геніально і справді найкраща відповідь, враховуючи, що підтримка браузера для calc дуже хороша.
Майкл

1
Ви можете зробити те ж саме, за винятком того, щоб додавати поле зліва, ви додаєте від’ємний запас праворуч (див. Stackoverflow.com/a/39289453/6015444 ).
Touniouk

2
Це рішення спричинить подібні проблеми з кольором тла, як відповідь "width: calc (100vw - 34px);" але з лівого боку.
Maciej Lew

1
Я рекомендую додати деякі медіа-запити до цього стилю @media screen and (min-width: 800px) {...} . У випадках, коли вміст буде відповідати ширині сторінки. Наприклад, у невеликих резолюціях виникне непотрібний пробіл, зміщення вмісту вправо
MarkosyanArtur

44

Я думаю, що не. Але стайлінг за bodyдопомогою overflow: scrollповинен робити. Ти, здається, це знаєш.


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

1
Так, але IIRC, це показує обидві смуги прокрутки. Мені не дуже потрібна горизонтальна.
Дмитро Нестерук

Це правда. Але я не дуже багато можу допомогти вам :( Насправді я вважаю лише перше речення моєї відповіді справжньою відповіддю, яка стосується питання.
Майкл Крелін - хакер

49
overflow-y: scroll:)
Свиш

2
Наступна краща відповідь
Самі

36

Якщо прокрутка завжди відображається, можливо, це не добре для компонування.

Спробуйте обмежити ширину тіла за допомогою css3

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

vw- ширина вікна перегляду (див. посилання для отримання додаткових пояснень).
calcОбчислити в css3
34pxозначає подвійну ширину смуги прокрутки (див. це для фіксованого або це для розрахунку, якщо ви не довіряєте фіксованим розмірам)


4
Все марність, поки комусь не потрібно.
Месіо

3
Це візуально набагато менш нав'язливо, ніж просто змушувати штрих-барів, як описана прийнята відповідь.
Silas Hansen

4
Це працювало найкраще для моїх потреб до цього часу, я також додав, padding-left: 34px;щоб рівномірно центрувати свою сторінку.
Пат Мільяччо

3
Це має бути прийнята відповідь, на відміну від прийнятої в даний час, вона фактично відповідає на питання!
Coz

2
Це спричинить проблеми, якщо ви маєте навігацію / заголовок іншого кольору, ніж фон тіла або нижню межу тощо
Zia Ul Rehman Mughal

28
html {
  overflow-x: hidden;
  margin-right: calc(-1 * (100vw - 100%));
}

Приклад . Натисніть кнопку "змінити мінімальну висоту".

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


Мені довелося покласти тіло в дів і застосувати поле до діву, щоб воно спрацювало (подібно до відповіді Рапті .) Але це виглядає так симпатичніше.
Touniouk

1
Це чудово працює і, здається, не призводить до небажаних горизонтальних смуг прокрутки в Chrome або Firefox. Чому б не просто використовувати calc(100% - 100vw)замість того, щоб множити на -1?
SystemParadox

13

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


13

Якщо ви змінюєте розмір або після завантаження деяких даних додаєте смугу прокрутки, ви можете спробувати слідувати, створити клас та застосувати цей клас.

.auto-scroll {
   overflow-y: overlay;
   overflow-x: overlay;
}

3

Я вирішив проблему на одному з моїх веб-сайтів, чітко встановивши ширину тіла в javascript на розмір вікна перегляду мінус ширину смуги прокрутки. Я використовую функцію , засноване JQuery документованої тут , щоб визначити ширину смуги прокрутки.

<body id="bodyid>

var bodyid = document.getElementById('bodyid');
bodyid.style.width = window.innerWidth - scrollbarWidth() + "px";

10
Я навіть не можу почати пояснювати, чому це така погана практика.
mythofechelon

20
@BenHooper: Я хотів би знати, чому це погана практика.
Саад

1
Що станеться, якщо змінити розмір вікна?
Бреден Стеффаняк

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, які завантажувач завантажує на все, під час огляду сторінки межа контейнера потрапляє під смугу прокрутки. Я подав заявку 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 Solution (коли 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елемента.


1
або змінити його на body {overflow-y: scroll}
Рубен

1
Але це завжди відображатиме смугу прокрутки, навіть якщо вона не потрібна.
Рапті

Ви повинні пояснити, чому ви встановлюєте ширину двічі? html { width: 100vw; }працював на мене
Хассан Тарек

Для мене це фактично створює дві смуги прокрутки
rbansal

2

У мене є ця проблема, але найпростіший спосіб її виправити це (це працює для мене):

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

body{overflow-y:scroll;}

як це просто! :)


2

Рішення, розміщені за допомогою calc (100vw - 100%), знаходяться на правильному шляху, але з цим виникає проблема: у вас назавжди залишиться запас лівого розміру смуги прокрутки, навіть якщо ви зміните розмір вікна, щоб вміст заповнює весь вікно перегляду.

Якщо ви спробуєте обійти це за допомогою медіа-запиту, у вас виникне незручний момент оснащення, оскільки маржа не буде прогресивно зменшуватися, коли ви зміните розмір вікна.

Ось таке рішення, яке подолає це, і AFAIK не має недоліків:

Замість того, щоб використовувати margin: auto для центрування вашого вмісту, використовуйте це:

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

Замініть 500px на половину максимальної ширини вашого вмісту (тому в цьому прикладі максимальна ширина вмісту дорівнює 1000px). Тепер вміст залишатиметься в центрі, а поле буде поступово зменшуватися до кінця, поки вміст не заповнить вікно перегляду.

Для того, щоб запобігти відходженню поля відсутності, коли вікно перегляду менша за максимальну ширину, просто додайте медіа-запит, як-от так:

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

Et voilà!


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;

Це змусить цей елемент ігнорувати смугу прокрутки, і він працює з кольором фону або зображеннями.


-3

Я вирішив цю проблему

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

$(document).ready(function(){
  $(window).load(function() {
    $('html').css({
      'overflow-y': ''
    });
  });
});

3
Ви, ймовірно, отримаєте поганий прийом вашої відповіді, оскільки для цього рішення потрібна вся рамка JavaScript. "jQuery всі речі!"
Пол Ламмерцма

3
так, jQuery, безумовно, шлях - doxdesk.com/img/updates/20091116-so-large.gif
Анонім

-4
@media screen and (min-width: 1024px){
    body {
    min-height: 700px
    }
}

Ласкаво просимо до переповнення стека! Хоча цей фрагмент коду може вирішити питання, у тому числі пояснення дійсно допомагає покращити якість вашої публікації. Пам'ятайте, що ви відповідаєте на запитання читачів у майбутньому, і ці люди можуть не знати причини вашої пропозиції щодо коду. Будь ласка, намагайтеся не переповнювати свій код пояснювальними коментарями, це зменшує читабельність і коду, і пояснень!
Ендрю Майєрс

-5

На відміну від прийнятої відповіді, яка передбачає постійну смугу прокрутки у вікні браузера, навіть якщо вміст не переповнює екран , я вважаю за краще використовувати:

html{
  height:101%;
}

Це тому, що поява прокрутки має більше сенсу, якщо вміст насправді переповнюється .

Це має більше сенсу, ніж це .


1
Принаймні, останнє речення неправильне у вашій відповіді. Це має сенс подібним із надлишком порожньої сторінки, надрукованої принтером.
vp_arth
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.