Просто відключити прокрутку не приховати її?


199

Я намагаюся вимкнути панель прокрутки html / body батьків, коли я використовую лайтбокс. Тут головне слово - відключити . Я не хочу цього приховувати overflow: hidden;.

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

Я хочу знати, чи можливо відключити смугу прокрутки, поки її показувати.


1
Чи можлива будь-яка прокрутка? (Чи є у лайтбокса якісь смуги прокрутки?)
Šime Vidas

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

у чому проблема використання лайтбокса зі смугою прокрутки?
manny

1
@Dejan Тому що я знаю, як відключити всі прокрутки - це відключить головну смугу прокрутки, а також ту, що знаходиться в лайтбоксі ...
Šime Vidas

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

Відповіді:


174

Якщо сторінку під накладом можна "зафіксувати" вгорі, коли ви відкриєте накладку, яку ви можете встановити

body { position: fixed; overflow-y:scroll }

ви все одно повинні бачити праву панель прокрутки, але вміст не прокручується. Коли ви закриєте накладку, просто поверніть ці властивості за допомогою

body { position: static; overflow-y:auto }

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

Оновлення

Ви також можете зробити невелике поліпшення: якщо ви отримаєте document.documentElement.scrollTopвластивість через javascript безпосередньо перед відкриттям шару, ви зможете динамічно призначити це значення як topвластивість елемента body: при такому підході сторінка буде стояти на своєму місці, незалежно від того, чи знову зверху або якщо ви вже прокручували.

Css

.noscroll { position: fixed; overflow-y:scroll }

JS

$('body').css('top', -(document.documentElement.scrollTop) + 'px')
         .addClass('noscroll');

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

4
з невеликою модифікацією це працює. я додав ширину: 100%; я пішов оновити моє питання з рішенням, але ви можете змінити своє з шириною: 100% ;? дякую за пропозицію
Dejan.S

3
Я не знаю чому, але це для мене краще: $('body').css('top', -($('body').scrollTop()) + 'px').addClass('noscroll');
PDXIII

4
@whitesiroi, ти маєш рацію. Я оновив скрипку: jsfiddle.net/evpozdniakov/2m8km9wg Дякую!
evpozdniakov

1
Для тих, хто читає коментарі до рішення, остання скрипка пропонує рішення для відключення та повторного включення смуги прокрутки, зберігаючи положення смуги прокрутки в обох випадках. Дякую!
користувач1063287

80

Чотири невеликі доповнення до обраного рішення:

  1. Застосовуйте "noscroll" до html замість body, щоб запобігти подвійним смугам прокрутки в IE
  2. Щоб перевірити, чи є насправді смуга прокрутки перш ніж додавати клас "noscroll". В іншому випадку сайт також буде стрибати, натиснувши новою смугою прокрутки, що не прокручується.
  3. Щоб зберегти будь-який можливий scrollTop, щоб вся сторінка не повернулася до початку (наприклад, оновлення Fabrizio, але вам потрібно схопити значення перед додаванням класу "noscroll")
  4. Не всі браузери обробляють scrollTop так само, як це зафіксовано на http://help.dottoro.com/ljnvjiow.php

Повне рішення, яке, здається, працює для більшості браузерів:

CSS

html.noscroll {
    position: fixed; 
    overflow-y: scroll;
    width: 100%;
}

Вимкнути прокрутку

if ($(document).height() > $(window).height()) {
     var scrollTop = ($('html').scrollTop()) ? $('html').scrollTop() : $('body').scrollTop(); // Works for Chrome, Firefox, IE...
     $('html').addClass('noscroll').css('top',-scrollTop);         
}

Увімкнути прокрутку

var scrollTop = parseInt($('html').css('top'));
$('html').removeClass('noscroll');
$('html,body').scrollTop(-scrollTop);

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


1
Це добре перевірено на робочому столі, але на iPhone він створив порожній білий екран, поки читач не спробував прокрутити сторінку. Після того, як читач намагався взаємодіяти зі сторінкою, передбачуваний екран став видимим із заблокованою прокруткою.
Майкл Халілі

Це прекрасно працювало з Fancybox на iPad, щоб відключити прокручування зображення лайтбоксу afterLoad()та afterCloseзворотній зв'язок. Може бути корисним для інших, хто шукає це питання.
Томанов

У частині "увімкнути прокрутку" ви можете видалити атрибут стилю, який розміщується на html-елементі після виклику "відключити прокрутку"; чи не так?
Бен

3
jQuery стандартизує нативні DOM scrollTopтакі, що рядок 2 коду "Вимкнути прокрутку" можна виразити як $( window ).scrollTop().
Барні

Я думаю, що до цього потрібно додати ще одне. У Chrome в OSX браузер може "перекручувати", надаючи прокрутці пружне відчуття. За допомогою цього коду, якщо ви знаходитесь у сірій області над або під сторінкою, і наведіть курсор миші на місце, де вимкнено прокрутку. Він приклеїться до місця над / під вікном браузера. З цієї причини вам потрібно додати перевірку на негативну величину прокрутки: if (scrollTop < 0) { scrollTop = 0; }. Ось повний код для відключення gist.github.com/jayd3e/2eefbbc571cd1668544b .
JayD3e

34

З включеною jQuery:


відключити

$.fn.disableScroll = function() {
    window.oldScrollPos = $(window).scrollTop();

    $(window).on('scroll.scrolldisabler',function ( event ) {
       $(window).scrollTop( window.oldScrollPos );
       event.preventDefault();
    });
};

включити

$.fn.enableScroll = function() {
    $(window).off('scroll.scrolldisabler');
};

використання

//disable
$("#selector").disableScroll();
//enable
$("#selector").enableScroll();

1
це було ідеально для мене, попередня відповідь змусила мою сторінку відскакувати, ця ні
Богдан Томі

радий , що я міг би допомогти, що вам може знадобитися , щоб перевірити «TouchMove» теж для мобільних пристроїв, вигуки
Ceed

Ну, це майже працювало для мене. Це творило чудеса в Windows (Firefox, Chrome) і MacOS в Firefox ... але потім я перейшов до Windows IE і Edge, а також MacOS в Chrome і Safari. Проблема була не у тому, що сторінка стрибає з боку на бік, але смуга прокрутки стрибала зверху до поточного положення або сторінка мерехтіла вгору. Людина, це було так , так близько. Можливо, ми ще можемо змусити його працювати.
Стівен Вентімілья

Це прекрасно працювало для мене, дякую! Ідеально для використання на веб-сайті, де меню накладень також знаходиться внизу сторінки!
SauriolJf

12

Я ОП

За допомогою відповіді від fcalderan я зміг сформувати рішення. Я залишаю тут своє рішення, оскільки воно чітко пояснює, як його використовувати, і додає дуже важливу деталь,width: 100%;

Додаю цей клас

body.noscroll
{
    position: fixed; 
    overflow-y: scroll;
    width: 100%;
}

це працювало для мене, і я використовував Fancyapp.


11

Це спрацювало дуже добре для мене….

// disable scrolling
$('body').bind('mousewheel touchmove', lockScroll);

// enable scrolling
$('body').unbind('mousewheel touchmove', lockScroll);


// lock window scrolling
function lockScroll(e) {
    e.preventDefault();
}

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

напр

$('button').on('click', function() {
     $('body').bind('mousewheel touchmove', lockScroll);
});

Це найкраща відповідь з усіх
Джафо

7

Ви не можете відключити подію прокрутки, але ви можете вимкнути пов’язані дії, які призводять до прокрутки, як-от миші та сенсорний рух:

$('body').on('mousewheel touchmove', function(e) {
      e.preventDefault();
});

4

Ви можете приховати смугу прокрутки тіла overflow: hiddenта встановити поле одночасно, щоб вміст не стрибав:

let marginRightPx = 0;
if(window.getComputedStyle) {
    let bodyStyle = window.getComputedStyle(document.body);
    if(bodyStyle) {
        marginRightPx = parseInt(bodyStyle.marginRight, 10);
    }
}

let scrollbarWidthPx = window.innerWidth - document.body.clientWidth;
Object.assign(document.body.style, {
    overflow: 'hidden',
    marginRight: `${marginRightPx + scrollbarWidthPx}px`
});

Після цього ви можете додати на сторінку відключену смугу прокрутки, щоб заповнити проміжок:

textarea {
  overflow-y: scroll;
  overflow-x: hidden;
  width: 11px;
  outline: none;
  resize: none;
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  border: 0;
}
<textarea></textarea>

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


1
Мені справді подобається цей метод найкраще. Дуже просто і чудово працює. Дякую!
dericcain

2

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

Це трохи стрибає IE, але працює як шарм у Firefox / Chrome.

var body = $("body"),
  overlay = $("#overlay"),
  overlayShown = false,
  overlayScrollListener = null,
  overlaySavedScrollTop = 0,
  overlaySavedScrollLeft = 0;

function showOverlay() {
  overlayShown = true;

  // Show overlay
  overlay.addClass("overlay-shown");

  // Save scroll position
  overlaySavedScrollTop = body.scrollTop();
  overlaySavedScrollLeft = body.scrollLeft();

  // Listen for scroll event
  overlayScrollListener = body.scroll(function() {
    // Scroll back to saved position
    body.scrollTop(overlaySavedScrollTop);
    body.scrollLeft(overlaySavedScrollLeft);
  });
}

function hideOverlay() {
  overlayShown = false;

  // Hide overlay
  overlay.removeClass("overlay-shown");

  // Turn scroll listener off
  if (overlayScrollListener) {
    overlayScrollListener.off();
    overlayScrollListener = null;
  }
}

// Click toggles overlay
$(window).click(function() {
  if (!overlayShown) {
    showOverlay();
  } else {
    hideOverlay();
  }
});
/* Required */
html, body { margin: 0; padding: 0; height: 100%; background: #fff; }
html { overflow: hidden; }
body { overflow-y: scroll; }

/* Just for looks */
.spacer { height: 300%; background: orange; background: linear-gradient(#ff0, #f0f); }
.overlay { position: fixed; top: 20px; bottom: 20px; left: 20px; right: 20px; z-index: -1; background: #fff; box-shadow: 0 0 5px rgba(0, 0, 0, .3); overflow: auto; }
.overlay .spacer { background: linear-gradient(#88f, #0ff); }
.overlay-shown { z-index: 1; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<h1>Top of page</h1>
<p>Click to toggle overlay. (This is only scrollable when overlay is <em>not</em> open.)</p>
<div class="spacer"></div>
<h1>Bottom of page</h1>
<div id="overlay" class="overlay">
  <h1>Top of overlay</h1>
  <p>Click to toggle overlay. (Containing page is no longer scrollable, but this is.)</p>
  <div class="spacer"></div>
  <h1>Bottom of overlay</h1>
</div>


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

@LeonWillens Я не впевнений, що ти маєш на увазі. Якщо ви стурбовані накладкою з'являється під фіксованим способом, то вам потрібно налаштувати z-indexна .overlay-shownбути більше , ніж фіксований заголовок. (У мене цей код працює у виробництві на сайті з фіксованим заголовком, і він працює чудово.)
0b10011

Ні, я говорив про смугу прокрутки bodyтегу. Я вчора експериментував з вашим кодом, і я маю виправлений заголовок у верхній частині сторінки. Якщо я обробляю прокрутку через bodyтег, панель прокрутки буде знаходитися під фіксованим заголовком.
Леон

1
@LeonWillens На жаль, я виправив це у виробництві в якийсь момент і забув оновити це. Схоже, замість того $("body"), що ми використовуємо $(window). І замість z-index: -1накладки, щоб приховати її, ви можете використовувати visibility: hiddenабо подібне. Див. Jsfiddle.net/8p2gfeha для швидкого тестування, щоб перевірити, чи працює він. Виправлений заголовок більше не з’являється вгорі панелі прокрутки. Я врешті спробую включити ці зміни у відповідь.
0b10011

Працює як шарм! Дякую :)
Леон

1

У мене була подібна проблема: ліве меню, яке, коли воно з’являється, запобігає прокрученню. Як тільки висота була встановлена ​​на 100vh, смуга прокрутки зникла, а вміст смикнувся праворуч.

Тож якщо ви не заперечуєте за тим, щоб увімкнути смугу прокрутки (але встановити вікно на повний зріст, щоб воно насправді нікуди не прокручувалося), тоді ще одна можливість - встановити крихітний нижній край, який дозволить утримувати смуги прокрутки:

body {
    height: 100vh;
    overflow: hidden;
    margin: 0 0 1px;
}

Чи не overflow:hiddenзаважає маржа мати якийсь ефект?
Коджа

0

ви можете зберегти переповнення: приховано, але керуйте положення прокрутки вручну:

перед тим, як показати зберегти фактичну позицію прокрутки:

var scroll = [$(document).scrollTop(),$(document).scrollLeft()];
//show your lightbox and then reapply scroll position
$(document).scrollTop(scroll[0]).scrollLeft(scroll[1]);

це має працювати


0

Грубим, але робочим способом буде примусити прокрутку повернутися до вершини, тим самим ефективно відключивши прокрутку:

var _stopScroll = false;
window.onload = function(event) {
    document.onscroll = function(ev) {
        if (_stopScroll) {
            document.body.scrollTop = "0px";
        }
    }
};

Коли ви відкриєте лайтбокс, підніміть прапор і, закривши його, опустіть прапор.

Живий тестовий випадок .


0

Мені подобається дотримуватися методу "overflow: hidden" і просто додати вкладку-право, що дорівнює ширині смуги прокрутки.

Отримайте функцію ширини смуги прокрутки за допомогою lostsource .

function getScrollbarWidth() {
    var outer = document.createElement("div");
    outer.style.visibility = "hidden";
    outer.style.width = "100px";
    outer.style.msOverflowStyle = "scrollbar"; // needed for WinJS apps

    document.body.appendChild(outer);

    var widthNoScroll = outer.offsetWidth;
    // force scrollbars
    outer.style.overflow = "scroll";

    // add innerdiv
    var inner = document.createElement("div");
    inner.style.width = "100%";
    outer.appendChild(inner);        

    var widthWithScroll = inner.offsetWidth;

    // remove divs
    outer.parentNode.removeChild(outer);

    return widthNoScroll - widthWithScroll;
}

Показуючи накладення, додайте клас "noscroll" у html та додайте padding-right to body:

$(html).addClass("noscroll");
$(body).css("paddingRight", getScrollbarWidth() + "px");

Приховуючи, вийміть клас та підкладку:

$(html).removeClass("noscroll");
$(body).css("paddingRight", 0);

Стиль noscroll як раз такий:

.noscroll { overflow: hidden; }

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


Я використав це рішення. Це допомогло мені уникнути подвійних смуг прокрутки (одна «порожня» для тіла, а друга - для вмісту накладання). Він також дуже добре працює на OSX, який може взагалі не відображати смуги прокрутки.
Novazembla

0

<div id="lightbox">знаходиться всередині <body>елемента, тому при прокручуванні лайтбокса ви також прокручуєте тіло. Рішення полягає в тому, щоб не поширювати <body>елемент на 100%, розміщувати довгий вміст всередині іншого divелемента та додавати смугу прокрутки, якщо потрібно, до цього divелемента overflow: auto.

html {
  height: 100%
}
body {
  margin: 0;
  height: 100%
}
#content {
  height: 100%;
  overflow: auto;
}
#lightbox {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}
<html>
  <body>
    <div id="content">much content</div>
    <div id="lightbox">lightbox<div>
  </body>
</html>

Тепер, прокрутка по лайтбоксі (і bodyтак само) не має ефекту, оскільки тіло не більше 100% від висоти екрана.


0

Усі модальні / лайтбокс-системи на основі JavaScript використовують переповнення під час відображення модального / лайтбоксу, на html-тезі або тезі body.

Коли відображається лайтбокс, js натискає переповнення, приховане на html або тег body. Коли лайтбокс прихований, деякі видаляють приховані, інші натискають автоматично на переповнення html або тегу body.

Розробники, які працюють на Mac, не бачать проблеми смуги прокрутки.

Просто замініть прихований відмененим, щоб не побачити вміст ковзання під модалом видалення прокрутки.

Лайтбокс відкрити / показати:

<html style="overflow: unset;"></html>

Лайтбокс закрити / приховати:

<html style="overflow: auto;"></html>

0

Якщо сторінку під накладом можна "зафіксувати" вгорі, коли ви відкриєте накладку, яку ви можете встановити

.disableScroll { position: fixed; overflow-y:scroll }

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

Щоб зберегти позицію сторінки, зробіть це в jquery

$('body').css('top', - ($(window).scrollTop()) + 'px').addClass('disableScroll');

Коли ви закриєте накладку, просто поверніть ці властивості за допомогою

var top = $('body').position().top;
$('body').removeClass('disableScroll').css('top', 0).scrollTop(Math.abs(top));

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


0

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

CSS

.no-scroll{
  position: fixed; 
  width:100%;
  min-height:100vh;
  top:0;
  left:0;
  overflow-y:scroll!important;
}

JS

var scrollTopPostion = 0;

function scroll_pause(){
  scrollTopPostion = $(window).scrollTop();
  $("body").addClass("no-scroll").css({"top":-1*scrollTopPostion+"px"});
}

function scroll_resume(){
  $("body").removeClass("no-scroll").removeAttr("style");
  $(window).scrollTop(scrollTopPostion);
}

Тепер все, що вам потрібно зробити, це викликати функції

$(document).on("click","#DISABLEelementID",function(){
   scroll_pause();
});

$(document).on("click","#ENABLEelementID",function(){
   scroll_resume();
});

-1

Ви можете це зробити за допомогою Javascript:

// Classic JS
window.onscroll = function(ev) {
  ev.preventDefault();
}

// jQuery
$(window).scroll(function(ev) {
  ev.preventDefault();
}

А потім відключіть його, коли ваш лайтбокс закритий.

Але якщо ваша лайтбокс містить смугу прокрутки, ви не зможете прокручувати її, поки вона відкрита. Це тому, що windowмістить і те, bodyі #lightbox. Отже, ви повинні використовувати таку архітектуру, як наступна:

<body>
  <div id="global"></div>
  <div id="lightbox"></div>
</body>

А потім застосувати onscrollподію лише на #global.

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