Chỉ cần vô hiệu hóa cuộn không ẩn nó?


198

Tôi đang cố gắng vô hiệu hóa thanh cuộn html / body của cha mẹ trong khi tôi đang sử dụng hộp đèn. Từ chính ở đây là vô hiệu hóa . Tôi không muốn giấu nó với overflow: hidden;.

Lý do cho điều này là overflow: hiddenlàm cho trang web nhảy và chiếm diện tích nơi cuộn.

Tôi muốn biết nếu có thể vô hiệu hóa thanh cuộn trong khi vẫn hiển thị nó.


1
Có nên cuộn bất kỳ? (Hộp đèn có bất kỳ thanh cuộn nào không?)
Vidime Vidas

Trang web đã cuộn nhưng tôi chỉ muốn tắt nó trong khi hộp đèn đang mở. tôi chỉ muốn biết nếu nó có thể vô hiệu hóa một thanh cuộn trong khi hiển thị nó. không có gì khác là cần thiết như làm thế nào để làm điều đó trong hộp đèn hoặc bất cứ điều gì khác.
Dejan.S

vấn đề khi sử dụng hộp đèn với thanh cuộn là gì?
manny

1
@Dejan Bởi vì tôi biết cách vô hiệu hóa tất cả các cuộn - điều đó sẽ vô hiệu hóa thanh cuộn chính, nhưng cũng là một trong hộp đèn ...
Šime Vidas

1
Xin vui lòng không chỉnh sửa câu trả lời vào bài viết này. Phần câu trả lời dưới đây là cho câu trả lời. Nếu bạn có câu trả lời cho câu hỏi của mình khác với câu trả lời bên dưới, bạn có thể thêm giải pháp của riêng mình vào lựa chọn câu trả lời.
intcreator

Câu trả lời:


173

Nếu trang bên dưới lớp phủ có thể được "cố định" ở trên cùng, khi bạn mở lớp phủ, bạn có thể đặt

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

bạn vẫn sẽ thấy thanh cuộn bên phải nhưng nội dung không thể cuộn được. Khi bạn đóng lớp phủ, chỉ cần hoàn nguyên các thuộc tính này với

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

Tôi chỉ đề xuất theo cách này chỉ vì bạn sẽ không cần thay đổi bất kỳ sự kiện cuộn nào

Cập nhật

Bạn cũng có thể cải thiện một chút: nếu bạn nhận được thuộc document.documentElement.scrollToptính qua javascript ngay trước khi mở lớp, bạn có thể tự động gán giá trị đó làm topthuộc tính của phần tử cơ thể: với cách tiếp cận này, trang sẽ đứng ở vị trí của nó, bất kể bạn ' trên đầu trang hoặc nếu bạn đã cuộn.

Css

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

Mã não

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

2
nó gây rối với bố cục của tôi nhưng với một số sửa đổi, nó chỉ có thể hoạt động. tôi thích điều này tôi sẽ thử nó nhiều hơn
Dejan.S

4
với một chút sửa đổi, đây là công trình. tôi đã thêm chiều rộng: 100%; Tôi đã cập nhật câu hỏi của tôi với giải pháp nhưng bạn có thể sửa đổi câu hỏi của mình với chiều rộng: 100%;? cảm ơn vì lời đề nghị
Dejan.S

3
Tôi không biết tại sao, nhưng điều này hoạt động tốt hơn đối với tôi: $('body').css('top', -($('body').scrollTop()) + 'px').addClass('noscroll');
PDXIII

4
@whitesiroi, bạn nói đúng. Tôi đã cập nhật fiddle: jsfiddle.net/evpozdniakov/2m8km9wg Cảm ơn bạn!
evpozdniakov

1
Đối với những người đọc các bình luận cho một giải pháp, fiddle cuối cùng cung cấp một giải pháp để vô hiệu hóa và kích hoạt lại thanh cuộn trong khi vẫn giữ vị trí thanh cuộn trong cả hai trường hợp. Cảm ơn!
dùng1063287

78

Bốn bổ sung nhỏ cho giải pháp đã chọn:

  1. Áp dụng 'noscroll' cho html thay vì cơ thể để ngăn các thanh cuộn đôi trong IE
  2. Để kiểm tra xem thực sự có một thanh cuộn trước khi thêm lớp 'noscroll' không. Nếu không, trang web cũng sẽ nhảy được đẩy bởi thanh cuộn không cuộn mới.
  3. Để giữ bất kỳ cuộn có thể nào để toàn bộ trang không quay trở lại đầu trang (như cập nhật của Fabrizio, nhưng bạn cần phải lấy giá trị trước khi thêm lớp 'noscroll')
  4. Không phải tất cả các trình duyệt đều xử lý scrollTop giống như tài liệu tại http://help.dottoro.com/ljnvjiow.php

Giải pháp hoàn chỉnh có vẻ hiệu quả với hầu hết các trình duyệt:

CSS

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

Vô hiệu hóa cuộn

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

Bật cuộn

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

Cảm ơn Fabrizio và Dejan đã đưa tôi đi đúng hướng và Brodingo cho giải pháp cho thanh cuộn đôi


1
Điều này đã thử nghiệm tốt trên máy tính để bàn nhưng trên iPhone, nó đã tạo ra một màn hình trắng cho đến khi người đọc cố gắng cuộn trang. Khi người đọc cố gắng tương tác với trang, màn hình dự định sẽ hiển thị khi cuộn cuộn bị khóa.
Michael Khalili

Điều này hoạt động hoàn hảo với Fancybox trên iPad để vô hiệu hóa cuộn hình ảnh hộp đèn afterLoad()afterClosegọi lại. Có thể hữu ích cho những người khác đang tìm kiếm câu hỏi này.
Tomanow

Trong phần "enable scroll", bạn có thể muốn xóa thuộc tính style được đặt trên phần tử html sau lệnh gọi "vô hiệu hóa cuộn"; không bạn
Ben

3
jQuery chuẩn hóa các DOM gốc scrollTopsao cho dòng 2 của mã 'Vô hiệu hóa cuộn' có thể được biểu thị dưới dạng $( window ).scrollTop().
Barney

Tôi nghĩ rằng một điều khác cần phải được thêm vào này. Trên Chrome trong OSX, trình duyệt có thể "cuộn quá mức", mang lại cảm giác đàn hồi. Với mã này nếu bạn đang ở trong vùng màu xám phía trên hoặc bên dưới trang và bạn di chuột qua một vị trí nơi bạn tắt cuộn. Nó sẽ dính vào một điểm trên / dưới cửa sổ trình duyệt. Vì lý do này, bạn cần thêm một kiểm tra cho giá trị cuộn âm : if (scrollTop < 0) { scrollTop = 0; }. Đây là mã đầy đủ để vô hiệu hóa gist.github.com/jayd3e/2eefbbc571cd1668544b .
JayD3e

34

Với jQuery được bao gồm:


vô hiệu hóa

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

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

cho phép

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

sử dụng

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

1
Điều này là hoàn hảo đối với tôi, câu trả lời trước đó đã khiến trang của tôi bị trả lại, câu này không
Bogdan Tomi

rất vui vì tôi có thể giúp, bạn cũng có thể cần kiểm tra "touchmove", đối với các thiết bị di động, chúc mừng
ceed

Vâng, điều này gần như làm việc cho tôi. Nó hoạt động kỳ diệu trên Windows (Firefox, Chrome) và MacOS trong Firefox ... nhưng sau đó tôi đã đi đến Windows IE và Edge, cùng với MacOS trong Chrome và Safari. Vấn đề không còn là việc trang nhảy từ bên này sang bên kia, mà thanh cuộn đã nhảy từ vị trí trên xuống vị trí hiện tại hoặc trang đang nhấp nháy trên cùng. Man, đây là như vậy , rất gần. Có lẽ chúng ta vẫn có thể làm cho nó hoạt động.
Steven Ventimiglia

Điều này làm việc hoàn hảo cho tôi, cảm ơn bạn! Sử dụng lý tưởng trên một trang web trong đó menu lớp phủ cũng ở dưới cùng của trang!
SauriolJf

12

Tôi là OP

Với sự giúp đỡ của câu trả lời từ fcalderan tôi đã có thể tạo thành một giải pháp. Tôi để giải pháp của mình ở đây vì nó mang lại sự rõ ràng về cách sử dụng nó và thêm một chi tiết rất quan trọng,width: 100%;

Tôi thêm lớp này

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

điều này làm việc cho tôi và tôi đã sử dụng Fancyapp.


11

Điều này làm việc rất tốt cho tôi ....

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

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


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

chỉ cần bọc hai dòng mã đó với bất kỳ quyết định nào khi bạn định khóa cuộn.

ví dụ

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

Đây là câu trả lời tốt nhất trong số tất cả
Jafo

7

Bạn không thể vô hiệu hóa sự kiện cuộn, nhưng bạn có thể vô hiệu hóa các hành động liên quan dẫn đến cuộn, như mousewheel và touchmove:

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

4

Bạn có thể ẩn thanh cuộn của cơ thể overflow: hiddenvà đặt lề cùng một lúc để nội dung không nhảy:

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`
});

Và sau đó bạn có thể thêm một thanh cuộn bị vô hiệu hóa vào trang để điền vào chỗ trống:

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>

Tôi đã làm chính xác điều này để thực hiện hộp đèn của riêng tôi. Có vẻ như đang làm việc tốt cho đến nay.


1
Tôi thực sự thích phương pháp này là tốt nhất. Rất đơn giản và làm việc tuyệt vời. Cảm ơn!
dericcain

2

Đây là giải pháp chúng tôi đã đi với. Chỉ cần lưu vị trí cuộn khi lớp phủ được mở, cuộn trở lại vị trí đã lưu bất cứ khi nào người dùng cố gắng cuộn trang và tắt trình nghe khi đóng lớp phủ.

Nó hơi khó hiểu trên IE, nhưng hoạt động như một nét quyến rũ trên 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>


Thực sự hoạt động, nhưng làm mờ thiết kế trong trường hợp tiêu đề cố định, khi thanh cuộn lặn dưới nó.
Leon Willens

@LeonWillens Tôi không chắc ý của bạn là gì. Nếu bạn đang lo lắng về lớp phủ xuất hiện bên dưới tiêu đề cố định, bạn sẽ cần phải điều chỉnh z-indexcủa .overlay-shownđể được lớn hơn tiêu đề cố định. (Tôi có mã này đang được sản xuất trên một trang web có tiêu đề cố định và nó hoạt động tốt.)
0b10011

Không, tôi đã nói về thanh cuộn của bodythẻ. Tôi đã thử nghiệm mã của bạn ngày hôm qua và tôi có một tiêu đề cố định ở đầu trang của tôi. Nếu tôi xử lý cuộn qua bodythẻ, thanh cuộn sẽ nằm dưới tiêu đề cố định.
Leon Willens

1
@LeonWillens Rất tiếc, có vẻ như tôi đã sửa lỗi này trong sản xuất tại một số điểm và quên cập nhật thông tin này. Có vẻ như thay vì $("body"), chúng tôi đang sử dụng $(window). Và thay vì z-index: -1trên lớp phủ để ẩn nó, bạn có thể sử dụng visibility: hiddenhoặc tương tự. Xem jsfiddle.net/8p2gfeha để kiểm tra nhanh để xem nó có hoạt động không. Đã sửa tiêu đề không còn xuất hiện trên đầu thanh cuộn. Cuối cùng tôi sẽ cố gắng kết hợp những thay đổi này vào câu trả lời.
0b10011

Hoạt động như một lá bùa! Cảm ơn bạn :)
Leon Willens

1

Tôi đã có một vấn đề tương tự: một menu bên trái, khi nó xuất hiện, ngăn cuộn. Ngay khi chiều cao được đặt thành 100vh, thanh cuộn biến mất và nội dung bị giật sang phải.

Vì vậy, nếu bạn không nhớ giữ thanh cuộn được bật (nhưng đặt cửa sổ ở độ cao đầy đủ để nó không thực sự cuộn ở bất cứ đâu) thì một khả năng khác là đặt lề dưới nhỏ, sẽ giữ cho thanh cuộn hiển thị:

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

Không phải overflow:hiddenngăn chặn lề có ảnh hưởng?
Koja

0

bạn có thể giữ tràn: ẩn nhưng quản lý vị trí cuộn theo cách thủ công:

trước khi hiển thị, hãy theo dõi vị trí cuộn thực tế:

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

nó nên hoạt động



0

Tôi thích bám vào phương thức "tràn: ẩn" và chỉ cần thêm phần đệm bên phải bằng với chiều rộng của thanh cuộn.

Nhận chức năng chiều rộng thanh cuộn, bởi mất nguồn .

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;
}

Khi hiển thị lớp phủ, hãy thêm lớp "noscroll" vào html và thêm phần đệm vào bên phải:

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

Khi ẩn, xóa lớp và phần đệm:

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

Phong cách noscroll chỉ là thế này:

.noscroll { overflow: hidden; }

Lưu ý rằng nếu bạn có bất kỳ phần tử nào có vị trí: đã sửa, bạn cũng cần thêm phần đệm vào các phần tử đó.


Tôi đã sử dụng giải pháp này. Nó giúp tôi tránh các thanh cuộn kép (một 'trống' cho phần thân và phần thứ hai cho nội dung của lớp phủ). Nó cũng hoạt động rất tốt trên OSX, có thể hoặc không thể hiển thị thanh cuộn nào cả.
Novazembla

0

<div id="lightbox">là bên trong <body>phần tử, do đó khi bạn cuộn hộp đèn, bạn cũng cuộn phần thân. Giải pháp là không mở rộng <body>phần tử trên 100%, đặt nội dung dài bên trong divphần tử khác và thêm thanh cuộn nếu cần cho divphần tử này với 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>

Bây giờ, cuộn qua hộp đèn (và bodycả) cũng không có tác dụng, vì thân máy không dài hơn 100% chiều cao màn hình.


0

Tất cả các hệ thống dựa trên javascript / modbox đều sử dụng tràn khi hiển thị modal / lightbox, trên thẻ html hoặc thẻ body.

Khi hộp đèn được hiển thị, js sẽ đẩy một ẩn tràn trên thẻ html hoặc thẻ body. Khi hộp đèn bị ẩn, một số loại bỏ ẩn khác đẩy tự động tràn trên thẻ html hoặc thẻ cơ thể.

Các nhà phát triển làm việc trên Mac, không thấy vấn đề của thanh cuộn.

Chỉ cần thay thế ẩn bằng một unset để không thấy nội dung bị trượt theo phương thức loại bỏ thanh cuộn.

Mở / hiển thị hộp đèn:

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

Đóng / ẩn hộp đèn:

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

0

Nếu trang bên dưới lớp phủ có thể được "cố định" ở trên cùng, khi bạn mở lớp phủ, bạn có thể đặt

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

cung cấp lớp này cho phần thân có thể cuộn, bạn vẫn sẽ thấy thanh cuộn bên phải nhưng nội dung không thể cuộn được.

Để duy trì vị trí của trang, hãy làm điều này trong jquery

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

Khi bạn đóng lớp phủ, chỉ cần hoàn nguyên các thuộc tính này với

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

Tôi chỉ đề xuất theo cách này chỉ vì bạn sẽ không cần thay đổi bất kỳ sự kiện cuộn nào


0

Điều này sẽ ngăn chế độ xem nhảy lên trên cùng bằng cách lưu vị trí cuộn và khôi phục nó khi bật cuộn.

CSS

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

Mã não

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);
}

Bây giờ tất cả những gì bạn cần làm là gọi các hàm

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

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

-1

Bạn có thể làm điều đó với Javascript:

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

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

Và sau đó vô hiệu hóa nó khi hộp đèn của bạn được đóng lại.

Nhưng nếu hộp đèn của bạn chứa thanh cuộn, bạn sẽ không thể cuộn trong khi mở. Điều này là do windowchứa cả body#lightbox. Vì vậy, bạn phải sử dụng một kiến ​​trúc như sau:

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

Và sau đó chỉ áp dụng onscrollsự kiện này #global.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.