Cuộn con div cuộn cửa sổ, làm cách nào để ngăn điều đó lại?


94

Tôi có một div, với một thanh cuộn, Khi nó đến cuối, trang của tôi bắt đầu cuộn. Có cách nào tôi có thể ngăn chặn hành vi này không?


2
@NGLN không phải là một câu hỏi trùng lặp, khác biệt.
sideinderguy

Câu trả lời:


68

Bạn có thể hủy kích hoạt tính năng cuộn của toàn bộ trang bằng cách làm như sau:

<div onmouseover="document.body.style.overflow='hidden';" onmouseout="document.body.style.overflow='auto';"></div>

33
Tốt, nhưng nó làm cho thanh cuộn của trình duyệt biến mất bất cứ khi nào bạn di chuột qua div.
cstack

@cstack bạn nói đúng đó là lý do tại sao câu trả lời của riêng OP (Jeevan) tốt hơn.
Imran Bughio

2
Nhiều bánh xe cuộn của trình duyệt biến mất và xuất hiện trở lại khi người dùng di chuyển chuột ngay bây giờ, vì vậy nhận xét trên không còn là vấn đề nữa.
Keith Holliday

Tuy nhiên, giải pháp này không hoạt động khi trang được nhúng trong iframe.
Gautam Krishnan

5
không phải là một giải pháp. đặt tràn thành ẩn sẽ ẩn thanh cuộn đột ngột định dạng lại tất cả nội dung của phần tử bên ngoài. ngoài ra, điều này giả định phần tử bên ngoài là body nhưng nó có thể là một div cuộn khác.
robisrob

43

Đã tìm ra giải pháp.

http://jsbin.com/itajok

Đây là những gì tôi cần.

Và đây là mã.

http://jsbin.com/itajok/edit#javascript,html

Sử dụng một Trình cắm jQuery.


Cập nhật do thông báo không dùng nữa

Từ jquery-mousewheel :

Hành vi cũ của việc thêm ba đối số ( delta, deltaXdeltaY) vào trình xử lý sự kiện hiện không được dùng nữa và sẽ bị xóa trong các bản phát hành sau.

Sau đó, event.deltaYbây giờ phải được sử dụng:

var toolbox = $('#toolbox'),
    height = toolbox.height(),
    scrollHeight = toolbox.get(0).scrollHeight;

toolbox.off("mousewheel").on("mousewheel", function (event) {
  var blockScrolling = this.scrollTop === scrollHeight - height && event.deltaY < 0 || this.scrollTop === 0 && event.deltaY > 0;
  return !blockScrolling;
});

Bản giới thiệu


6
Sử dụng liên kết của bạn GitHub cho js và phá vỡ vì content-type blah blah đây này một công trình: jsbin.com/itajok/207
Michael J. Calkins

Cả hai jsbins dường như không hoạt động trong trình giả lập thiết bị Chrome và trên iPhone. Có ai biết nếu điều này vẫn còn hoạt động?
Dirk Boer

2
"Giải pháp" của bạn chỉ hoạt động cho các sự kiện cuộn chuột, không phải trang lên / xuống hoặc phím mũi tên.
Scott

Tại sao "tắt" được yêu cầu ở đây?
Brad Johnson

16

Giải pháp được chọn là một tác phẩm nghệ thuật. Nghĩ rằng nó xứng đáng là một plugin ....

$.fn.scrollGuard = function() {
    return this
        .on( 'wheel', function ( e ) {
            var event = e.originalEvent;
            var d = event.wheelDelta || -event.detail;
            this.scrollTop += ( d < 0 ? 1 : -1 ) * 30;
            e.preventDefault();
        });
};    

Đây là một sự bất tiện liên tục đối với tôi và giải pháp này quá sạch so với các bản hack khác mà tôi đã thấy. Tò mò muốn biết thêm về cách nó hoạt động và nó sẽ được hỗ trợ rộng rãi như thế nào, nhưng hãy cổ vũ cho Jeevan và bất cứ ai ban đầu đã nghĩ ra điều này. BTW - trình soạn thảo câu trả lời stackoverflow cần điều này!

CẬP NHẬT

Tôi tin rằng điều này tốt hơn ở chỗ nó không cố gắng thao túng DOM, chỉ ngăn chặn sự tạo bọt có điều kiện ...

$.fn.scrollGuard2 = function() {
  return this
    .on( 'wheel', function ( e ) {
      var $this = $(this);
      if (e.originalEvent.deltaY < 0) {
        /* scrolling up */
        return ($this.scrollTop() > 0);
      } else {
        /* scrolling down */
        return ($this.scrollTop() + $this.innerHeight() < $this[0].scrollHeight);
      }
    })
  ;
};    

Hoạt động tốt trong chrome và đơn giản hơn nhiều so với các giải pháp khác ... hãy cho tôi biết nó hoạt động như thế nào ở những nơi khác ...

VĨ CẦM


3
thêm sự kiện DOMMouseScroll làm cho nó làm việc với Firefox → jsfiddle.net/chodorowicz/egqy7mbz/1
chodorowicz

Tôi ngạc nhiên là điều này không được viết thành jquery. Tôi nghĩ một trong những điểm chính là không cần quan tâm đến trình duyệt bạn đang sử dụng.
robisrob

thực sự có vẻ như cả hai đều bị phản đối ... wheelsự kiện
robisrob

Điều này dẫn đến việc cuộn trong Chrome trên Macbook của tôi bị giật nhanh hơn đáng kể. Giải pháp được chấp nhận không có vấn đề này.
danvk

đáng thất vọng. có rất nhiều phiên bản khác nhau của điều này. có vẻ như là một khía cạnh quan trọng của ui, và thực sự đáng ngạc nhiên khi đây là hành vi mặc định khi nó quá không trực quan. Rõ ràng là trình duyệt được trang bị để biết div cuộn bên trong đang ở giới hạn của nó để có thể áp dụng sự kiện vào cửa sổ thay thế, vậy tại sao không có sẵn các chốt điều khiển để truy vấn nó?
robisrob

8

Bạn có thể sử dụng sự kiện di chuột qua div để tắt thanh cuộn nội dung và sau đó là sự kiện di chuột để kích hoạt lại nó?

Ví dụ: HTML

<div onmouseover="disableBodyScroll();" onmouseout="enableBodyScroll();">
    content
</div>

Và sau đó javascript như vậy:

var body = document.getElementsByTagName('body')[0];
function disableBodyScroll() {
    body.style.overflowY = 'hidden';
}
function enableBodyScroll() {
    body.style.overflowY = 'auto';
}

12
Bạn cũng có thể sử dụng document.bodythay thế.
Ry-

8

Đây là một cách trình duyệt chéo để thực hiện việc này trên trục Y, nó hoạt động trên máy tính để bàn và thiết bị di động. Đã thử nghiệm trên OSX và iOS.

var scrollArea = this.querySelector(".scroll-area");
scrollArea.addEventListener("wheel", function() {
    var scrollTop = this.scrollTop;
    var maxScroll = this.scrollHeight - this.offsetHeight;
    var deltaY = event.deltaY;
    if ( (scrollTop >= maxScroll && deltaY > 0) || (scrollTop === 0 && deltaY < 0) ) {
        event.preventDefault();
    }
}, {passive:false});

scrollArea.addEventListener("touchstart", function(event) {
    this.previousClientY = event.touches[0].clientY;
}, {passive:false});

scrollArea.addEventListener("touchmove", function(event) {
    var scrollTop = this.scrollTop;
    var maxScroll = this.scrollHeight - this.offsetHeight;
    var currentClientY = event.touches[0].clientY;
    var deltaY = this.previousClientY - currentClientY;
    if ( (scrollTop >= maxScroll && deltaY > 0) || (scrollTop === 0 && deltaY < 0) ) {
        event.preventDefault();
    }
    this.previousClientY = currentClientY;
}, {passive:false});

Điều này hoạt động tuyệt vời! Chà, chính xác những gì tôi đã tìm kiếm. Nó chắc chắn cần nhiều lượt ủng hộ hơn.
delato468

Giải pháp này hoạt động khá tốt nhưng cần điều chỉnh một chút: cần thay đổi scrollTop === maxScroll từng thứ scrollTop >= maxScroll. Nó có vẻ là lạ bởi vào 1 trường hợp, nó là cần thiết
tchiot.ludo

7

Tôi đã viết giải quyết cho vấn đề này

  var div;
  div = document.getElementsByClassName('selector')[0];

  div.addEventListener('mousewheel', function(e) {
    if (div.clientHeight + div.scrollTop + e.deltaY >= div.scrollHeight) {
      e.preventDefault();
      div.scrollTop = div.scrollHeight;
    } else if (div.scrollTop + e.deltaY <= 0) {
      e.preventDefault();
      div.scrollTop = 0;
    }
  }, false);

Một trong số ít giải pháp ở đây hoạt động mà không làm các phần tử trang bị nhảy một cách khó chịu do tính năng ẩn tràn đang được thiết lập.
Skeptic

+1 đây là một dung dịch rắn. nếu bạn đính kèm cái này vào một vùng chứa có thể cuộn, bạn sẽ muốn div trong ví dụ này là e.currentTarget.
Matt

dung dịch rất sạch. Cảm ơn
Thịnh Bùi

Đã hoạt động trong Chrome 61.0.3163.100 và Safari 11.0, nhưng không hoạt động trong FireFox 56.0 (Mac OS El Capitan)
BigJ

Đây là giải pháp gốc tốt nhất. Tuy nhiên, falsekhông cần phải chỉ định addEventListenervì đó là mặc định. Hơn nữa, các phép so sánh phải là các bất đẳng thức đơn giản ( ><), không phải >=hoặc <=.
Câu hỏi Quolonel

6

Nếu tôi hiểu câu hỏi của bạn một cách chính xác, thì bạn muốn ngăn việc cuộn nội dung chính khi chuột qua một div (giả sử là một thanh bên). Vì vậy, thanh bên có thể không phải là phần tử con của vùng chứa cuộn của nội dung chính (vốn là cửa sổ trình duyệt), để ngăn sự kiện cuộn xảy ra với cha của nó.

Điều này có thể yêu cầu một số thay đổi đánh dấu theo cách sau:

<div id="wrapper"> 
    <div id="content"> 
    </div> 
</div> 
<div id="sidebar"> 
</div> 

Xem nó hoạt động trong fiddle mẫu này và so sánh với fiddle mẫu này có hành vi rời chuột hơi khác của thanh bên.

Xem thêm chỉ cuộn một div cụ thể với thanh cuộn chính của trình duyệt .


Trong trường hợp này, thanh bên nằm ngoài div wrapper. Vì vậy, tôi không nghĩ rằng các cuộn chí bong bóng để phụ huynh
Jeevan

Bởi "trường hợp này" bạn có nghĩa là trường hợp của bạn? Nếu không: bạn hoàn toàn đúng. Nếu vậy: nếu trang của bạn cuộn vào cuối div scrolling, thì thông báo cuộn bong bóng đến div cha, vì vậy tôi nghĩ rằng trang của bạn và div không phải là anh chị em, mà là cha và con.
NGLN

Có, Trang là cha của div của tôi, Vì vậy, khi đến cuối, nó bắt đầu cuộn trang mà tôi không muốn.
Jeevan

Nếu bạn không thể đặt div của mình trở thành anh chị em của nội dung chính, thì vấn đề này không thể được khắc phục chỉ với HTML + CSS. Đó là hành vi mặc định.
NGLN

1
Tôi nghĩ đây là giải pháp hiệu quả nhất trong tất cả các câu trả lời được cung cấp; với đánh dấu rõ ràng tốt ở cuối trang, cần ít tấn công CSS và JS hơn nhiều để có được hành vi mong muốn.

6

Như đã trả lời ở đây , hầu hết các trình duyệt hiện đại hiện nay đều hỗ trợ thuộc tính overscroll-behavior: none;CSS, ngăn chặn chuỗi cuộn. Và đó là nó, chỉ một dòng!


2
Đây sẽ là câu trả lời chính xác vào năm 2020. Đối với trường hợp sử dụng của tôi, giải pháp tốt nhất là overscroll-behavior: contain;.
Pier

3

điều này sẽ vô hiệu hóa việc cuộn trên cửa sổ nếu bạn nhập phần tử bộ chọn. hoạt động giống như bùa.

elements = $(".selector");

elements.on('mouseenter', function() {
    window.currentScrollTop = $(window).scrollTop();
    window.currentScrollLeft = $(window).scrollTop();
    $(window).on("scroll.prevent", function() {
        $(window).scrollTop(window.currentScrollTop);
        $(window).scrollLeft(window.currentScrollLeft);
    });
});

elements.on('mouseleave', function() {
    $(window).off("scroll.prevent");
});

Đây thực sự là một giải pháp hiệu quả. Tôi cần nó trong js thuần túy, vì vậy tôi đã viết lại nó. Nếu ai cần, nó ở đây . Đối với bất kỳ ai vẫn đang tìm kiếm giải pháp, bạn nên xem câu trả lời của tôi dưới đây .
Andriy Stolyar

2

Bạn có thể hủy kích hoạt tính năng cuộn của toàn bộ trang bằng cách làm như thế này nhưng hãy hiển thị thanh cuộn!

<div onmouseover="document.body.style.overflow='hidden'; document.body.style.position='fixed';" onmouseout="document.body.style.overflow='auto'; document.body.style.position='relative';"></div>

2
$this.find('.scrollingDiv').on('mousewheel DOMMouseScroll', function (e) {
  var delta = -e.originalEvent.wheelDelta || e.originalEvent.detail;
  var scrollTop = this.scrollTop;
  if((delta < 0 && scrollTop === 0) || (delta > 0 && this.scrollHeight - this.clientHeight - scrollTop === 0)) {
    e.preventDefault();
  }
});

1

Dựa trên câu trả lời của ceed, đây là phiên bản cho phép lồng các phần tử được bảo vệ cuộn. Chỉ có phần tử di chuột qua sẽ cuộn, và nó cuộn khá trơn tru. Phiên bản này cũng được tham gia lại. Nó có thể được sử dụng nhiều lần trên cùng một phần tử và sẽ loại bỏ và cài đặt lại các trình xử lý một cách chính xác.

jQuery.fn.scrollGuard = function() {
    this
        .addClass('scroll-guarding')
        .off('.scrollGuard').on('mouseenter.scrollGuard', function() {
            var $g = $(this).parent().closest('.scroll-guarding');
            $g = $g.length ? $g : $(window);
            $g[0].myCst = $g.scrollTop();
            $g[0].myCsl = $g.scrollLeft();
            $g.off("scroll.prevent").on("scroll.prevent", function() {
                $g.scrollTop($g[0].myCst);
                $g.scrollLeft($g[0].myCsl);
            });
        })
        .on('mouseleave.scrollGuard', function() {
            var $g = $(this).parent().closest('.scroll-guarding');
            $g = $g.length ? $g : $(window);
            $g.off("scroll.prevent");
        });
};

Một cách dễ dàng để sử dụng là thêm một lớp, chẳng hạn như scroll-guard, vào tất cả các phần tử trong trang mà bạn cho phép cuộn trên đó. Sau đó sử dụng $('.scroll-guard').scrollGuard()để bảo vệ chúng.


0

Nếu bạn áp dụng một overflow: hiddenphong cách, nó sẽ biến mất

chỉnh sửa: thực ra tôi đã đọc nhầm câu hỏi của bạn, điều đó sẽ chỉ ẩn thanh cuộn nhưng tôi không nghĩ đó là những gì bạn đang tìm kiếm.


1
Tôi cần cả thanh cuộn. Đang nói về hành vi. Khi tôi cuộn bằng con lăn chuột khi đến cuối cuộn của div, nó không được cuộn hết trang.
Jeevan

0

Tôi không thể nhận được bất kỳ câu trả lời nào để hoạt động trong Chrome và Firefox, vì vậy tôi đã nghĩ ra sự kết hợp này:

$someElement.on('mousewheel DOMMouseScroll', scrollProtection);

function scrollProtection(event) {
    var $this = $(this);
    event = event.originalEvent;
    var direction = (event.wheelDelta * -1) || (event.detail);
    if (direction < 0) {
        if ($this.scrollTop() <= 0) {
            return false;
        }
    } else {
        if ($this.scrollTop() + $this.innerHeight() >= $this[0].scrollHeight) {
            return false;
        }
    }
}
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.