Cách vô hiệu hóa cuộn trang bằng lập trình với jQuery


163

Sử dụng jQuery, tôi muốn tắt tính năng cuộn của cơ thể:

Ý tưởng của tôi là:

  1. Bộ body{ overflow: hidden;}
  2. Nắm bắt hiện tại scrollTop();/scrollLeft()
  3. Liên kết với sự kiện cuộn cơ thể, đặt scrollTop / scrollLeft thành giá trị đã chụp.

Có cách nào tốt hơn?


Cập nhật:

Vui lòng xem ví dụ của tôi và lý do tại sao, tại http://jsbin.com/ikuma4/2/edit

Tôi biết ai đó sẽ nghĩ "tại sao anh ta không chỉ sử dụng position: fixedbảng điều khiển?".

Xin đừng đề nghị điều này vì tôi có lý do khác.


7
"Có cách nào tốt hơn?" - ngoài việc để trình duyệt hoạt động bình thường?
Fenton

22
"khoa trương"?
Mike Weller

6
Có lẽ có nghĩa là lập trình? Vì đó là gợi ý sửa lỗi chính tả hàng đầu của firefox cho 'lập trình'
Michael Shimmins

4
Chủ đề này sẽ diễn ra \ b \
Cipi

3
@Sohnee vô hiệu hóa cuộn! == xấu
Mansiemans

Câu trả lời:


136

Cách duy nhất tôi tìm thấy để làm điều này tương tự như những gì bạn mô tả:

  1. Lấy vị trí cuộn hiện tại (đừng quên trục ngang!).
  2. Đặt tràn thành ẩn (có thể muốn giữ lại giá trị tràn trước đó).
  3. Di chuyển tài liệu đến vị trí cuộn được lưu trữ với scrollTo ().

Sau đó, khi bạn đã sẵn sàng cho phép cuộn lại, hãy hoàn tác tất cả những thứ đó.

Chỉnh sửa: không có lý do gì tôi không thể cung cấp cho bạn mã kể từ khi tôi gặp rắc rối để đào nó lên ...

// lock scroll position, but retain settings for later
var scrollPosition = [
  self.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
  self.pageYOffset || document.documentElement.scrollTop  || document.body.scrollTop
];
var html = jQuery('html'); // it would make more sense to apply this to body, but IE7 won't have that
html.data('scroll-position', scrollPosition);
html.data('previous-overflow', html.css('overflow'));
html.css('overflow', 'hidden');
window.scrollTo(scrollPosition[0], scrollPosition[1]);


// un-lock scroll position
var html = jQuery('html');
var scrollPosition = html.data('scroll-position');
html.css('overflow', html.data('previous-overflow'));
window.scrollTo(scrollPosition[0], scrollPosition[1])

2
vui lòng xem jsbin.com/ikuma4/2/edit và giải thích bất kỳ lý do nào cho tôi rằng bạn tốt hơn? tôi có thiếu điều gì không (tôi hỏi vì tôi không thể thấy bất kỳ lý do nào cho độ dài câu trả lời của bạn so với ví dụ của tôi)
Hailwood

3
Cách tiếp cận của bạn không hoạt động trong IE7. Tôi cũng đã thử nó trước. Vấn đề là nó không phản ứng với sự kiện cuộn đủ nhanh. Nó cho phép cuộn tài liệu, sau đó chụp lại khi mã JS của bạn đặt lại vị trí cuộn trở lại nơi bạn muốn.
tfe

1
Ngoài ra, nếu cơ thể có quá nhiều thứ khác auto, nó sẽ bị ghi đè. Tôi cần phải duy trì cài đặt hiện có, do đó cũng thêm một số chi phí.
tfe

Có ai biết tại sao chỉ đơn giản là tạo kiểu htmlbodyvới overflow: hiddenlà không đủ? Chúng tôi cuối cùng vẫn cần xử lý sự kiện.
kpozin

4
Đây là một câu trả lời tuyệt vời. Và để làm cho nó hoạt động trên các thiết bị cảm ứng, hãy xem câu trả lời này .
Patrick

235

Điều này sẽ hoàn toàn vô hiệu hóa cuộn:

$('html, body').css({
    overflow: 'hidden',
    height: '100%'
});

Để khôi phục lại:

$('html, body').css({
    overflow: 'auto',
    height: 'auto'
});

Đã thử nghiệm nó trên Firefox và Chrome.


18
hoạt động như mong đợi. Cảm ơn! Đây nên là câu trả lời được chấp nhận!
Dave Chen

6
Vẫn cuộn với nút chuột giữa trên chrome.
Lothar

16
Điều này làm mất vị trí cuộn hiện tại. OP đã đề cập rõ ràng về việc nắm bắt vị trí cuộn, vì vậy tôi cho rằng anh ta yêu cầu điều đó. Dù sao, tôi yêu cầu nó, vì vậy đây là hạn chế sử dụng đối với tôi
zerm 26/11/13

7
PS Bỏ qua việc height: 100%khóa cuộn hiệu quả ở vị trí hiện tại mà không cần nhảy - ít nhất là trên Chrome mới nhất.
zerm

2
Đây KHÔNG phải là câu trả lời đúng. Vị trí cuộn không được chụp
taylorcressy

43

thử cái này

$('#element').on('scroll touchmove mousewheel', function(e){
  e.preventDefault();
  e.stopPropagation();
  return false;
})

chỉ là những gì tôi đang tìm kiếm ... gần như. Dù sao để vô hiệu hóa nó trong các phím mũi tên?
Cody

2
@Cody - kết hợp điều này với tràn css: ẩn
Darius.V

2
@cubbiu làm sao để đảo ngược?
Meer

3
Bạn có thể sử dụng$('#element').off('scroll touchmove mousewheel');
arnuschky

1
Giải pháp tuyệt vời. Mặc dù làm thế nào bạn chỉ vô hiệu hóa bodycuộn nhưng vẫn cho phép cuộn trong các phần tử con khác có overflow: scroll?
Fizzix

27

Tôi chỉ cung cấp một chút điều chỉnh cho giải pháp bằng tfe . Cụ thể, tôi đã thêm một số điều khiển bổ sung để đảm bảo rằng không có sự dịch chuyển nội dung trang (còn gọi là dịch chuyển trang ) khi thanh cuộn được đặt thành hidden.

Hai chức năng Javascript lockScroll()unlockScroll()có thể được xác định tương ứng để khóa và mở khóa cuộn trang.

function lockScroll(){
    $html = $('html'); 
    $body = $('body'); 
    var initWidth = $body.outerWidth();
    var initHeight = $body.outerHeight();

    var scrollPosition = [
        self.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
        self.pageYOffset || document.documentElement.scrollTop  || document.body.scrollTop
    ];
    $html.data('scroll-position', scrollPosition);
    $html.data('previous-overflow', $html.css('overflow'));
    $html.css('overflow', 'hidden');
    window.scrollTo(scrollPosition[0], scrollPosition[1]);   

    var marginR = $body.outerWidth()-initWidth;
    var marginB = $body.outerHeight()-initHeight; 
    $body.css({'margin-right': marginR,'margin-bottom': marginB});
} 

function unlockScroll(){
    $html = $('html');
    $body = $('body');
    $html.css('overflow', $html.data('previous-overflow'));
    var scrollPosition = $html.data('scroll-position');
    window.scrollTo(scrollPosition[0], scrollPosition[1]);    

    $body.css({'margin-right': 0, 'margin-bottom': 0});
}

nơi tôi giả định rằng <body>không có ký quỹ ban đầu.

Lưu ý rằng, mặc dù giải pháp trên hoạt động trong hầu hết các trường hợp thực tế, nhưng nó không dứt khoát vì nó cần một số tùy chỉnh thêm cho các trang bao gồm, ví dụ, một tiêu đề với position:fixed. Hãy đi vào trường hợp đặc biệt này với một ví dụ. Giả sử có

<body>
<div id="header">My fixedheader</div>
<!--- OTHER CONTENT -->
</body>

với

#header{position:fixed; padding:0; margin:0; width:100%}

Sau đó, người ta nên thêm các chức năng sau lockScroll()unlockScroll():

function lockScroll(){
    //Omissis   


    $('#header').css('margin-right', marginR);
} 

function unlockScroll(){
    //Omissis   

    $('#header').css('margin-right', 0);
}

Cuối cùng, hãy quan tâm đến một số giá trị ban đầu có thể cho lề hoặc phần đệm.


4
Bạn có một lỗi trong javascript $ body.css ({'lề-phải': 0, 'lề-dưới', 0}); phải là $ body.css ({'lề-phải': 0, 'lề-dưới': 0});
Johansrk

Trên thực tế, chỉ cần sử dụng marginRightmarginLeft:)
Martijn

25

bạn có thể sử dụng mã này:

$("body").css("overflow", "hidden");

8
Bạn vẫn có thể sử dụng nút chuột giữa để cuộn.
Roger Far

2
Không, cái này ổn và không có cuộn với cái này!
mr.soroush

Nếu bạn sử dụng một số css bổ sung, bạn hoàn toàn có thể tắt cuộn, xem câu trả lời của tôi để biết thêm chi tiết.
gitaarik

21

Để tắt TẮT cuộn, hãy thử điều này:

var current = $(window).scrollTop();
$(window).scroll(function() {
    $(window).scrollTop(current);
});

để thiết lập lại:

$(window).off('scroll');

Đây là một giải pháp tuyệt vời cho những gì tôi cần.
Terry Carter

@EveryScreamer không, nó làm cho màn hình rung lên như điên. Cố gắng tìm một cách giải quyết.
Telary

5

Tôi đã viết một plugin jQuery để xử lý việc này: $ .disablescroll .

Nó ngăn việc cuộn từ các sự kiện di chuột, touchmove và nhấn phím, chẳng hạn như Page Down.

Có một bản demo ở đây .

Sử dụng:

$(window).disablescroll();

// To re-enable scrolling:
$(window).disablescroll("undo");

Tôi đã cố gắng sử dụng plugin disablescroll () của bạn để tạm thời vô hiệu hóa cuộn khi nghe sự kiện mouswheel / scroll, nhưng nó không hoạt động. Bất kỳ cơ hội bạn biết một cách để đạt được hiệu quả đó?
thánh vàng

@JB Tôi có thể giúp, nhưng ý kiến ​​không phải là nơi tốt nhất. Tham gia cùng tôi trong trò chuyện tràn chồng này và tôi sẽ thấy những gì tôi có thể làm: chat.stackoverflow.com/rooms/55043/disablescroll-usage
Josh Harrison

Tôi xin lỗi, nhưng plugin này thậm chí không hoạt động trong jsfiddle của bạn.
markj

Bạn có thể giúp tôi kiểm tra điều này bằng cách cho tôi biết trình duyệt / nền tảng nào dường như không hoạt động?
Josh Harrison

5

Bạn có thể đính kèm một chức năng để cuộn các sự kiện và ngăn chặn hành vi mặc định của nó.

var $window = $(window);

$window.on("mousewheel DOMMouseScroll", onMouseWheel);

function onMouseWheel(e) {
    e.preventDefault();
}

https://jsfiddle.net/22cLw9em/


1
Đây là câu trả lời đúng. Không biết tại sao nó không được đặt như vậy
Guilherme Ferreira

Nó hoạt động. Chỉ cần mã đặt lại được đăng để khớp với câu trả lời của Patricks
Hastig Zusammenstellen

4

Một lớp lót để vô hiệu hóa cuộn bao gồm nút chuột giữa.

$(document).scroll(function () { $(document).scrollTop(0); });

chỉnh sửa : Dù sao cũng không cần jQuery, bên dưới giống như trên trong vanilla JS (có nghĩa là không có khung, chỉ có JavaScript):

document.addEventListener('scroll', function () { this.documentElement.scrollTop = 0; this.body.scrollTop = 0; })

this.documentEuity.scrollTop - tiêu chuẩn

this .body.scrollTop - Tương thích IE




3

Ai đó đã đăng mã này, có vấn đề không giữ được vị trí cuộn khi được khôi phục. Lý do là mọi người có xu hướng áp dụng nó cho html và cơ thể hoặc chỉ cơ thể nhưng nó chỉ nên được áp dụng cho html. Cách này khi được khôi phục vị trí cuộn sẽ được giữ:

$('html').css({
    'overflow': 'hidden',
    'height': '100%'
});

Để khôi phục lại:

$('html').css({
    'overflow': 'auto',
    'height': 'auto'
});

không 'overflow': 'auto',sử dụng'overflow': 'initial',
evtuhovdo

2

Điều này có thể hoặc có thể không hoạt động cho mục đích của bạn, nhưng bạn có thể mở rộng jScrollPane để kích hoạt chức năng khác trước khi cuộn. Tôi chỉ mới thử nghiệm điều này một chút, nhưng tôi có thể xác nhận rằng bạn có thể nhảy vào và ngăn chặn việc cuộn hoàn toàn. Tất cả những gì tôi đã làm là:

  • Tải xuống zip demo: http://github.com/vitch/jScrollPane/archives/master
  • Mở bản demo "Sự kiện" (event.html)
  • Chỉnh sửa nó để sử dụng nguồn tập lệnh không được rút gọn: <script type="text/javascript" src="script/jquery.jscrollpane.js"></script>
  • Trong jquery.jscrollpane.js, chèn "return;" tại dòng 666 (số dòng tốt lành! nhưng trong trường hợp phiên bản của bạn hơi khác, đây là dòng đầu tiên của positionDragY(destY, animate)chức năng

Bật các sự kiện.html và bạn sẽ thấy một hộp cuộn thông thường do sự can thiệp mã hóa của bạn sẽ không cuộn.

Bạn có thể kiểm soát toàn bộ thanh cuộn của trình duyệt theo cách này (xem fullpage_scroll.html).

Vì vậy, có lẽ bước tiếp theo là thêm một cuộc gọi đến một số chức năng khác tắt và thực hiện phép thuật neo của bạn, sau đó quyết định có tiếp tục cuộn hay không. Bạn cũng đã có các lệnh gọi API để đặt scrollTop và scrollLeft.

Nếu bạn muốn được giúp đỡ nhiều hơn, đăng bài nơi bạn nhận được!

Hy vọng điều này đã giúp.



1

Nếu bạn chỉ muốn tắt tính năng cuộn bằng điều hướng bàn phím, bạn có thể ghi đè sự kiện phím tắt.

$(document).on('keydown', function(e){
    e.preventDefault();
    e.stopPropagation();
});

1

Hãy thử mã này:

    $(function() { 
        // ...

        var $body = $(document);
        $body.bind('scroll', function() {
            if ($body.scrollLeft() !== 0) {
                $body.scrollLeft(0);
            }
        });

        // ...
    });

0

Bạn có thể che cửa sổ bằng một div có thể cuộn để ngăn cuộn nội dung trên một trang. Và, bằng cách ẩn và hiển thị, bạn có thể khóa / mở khóa cuộn của mình.

Làm một cái gì đó như thế này:

#scrollLock {
    width: 100%;
    height: 100%;
    position: fixed;
    overflow: scroll;
    opacity: 0;
    display:none
}

#scrollLock > div {
    height: 99999px;
}

function scrollLock(){
    $('#scrollLock').scrollTop('10000').show();
}

function scrollUnlock(){
    $('#scrollLock').hide();
}

7
Vui lòng không sử dụng các chữ viết tắt như "u" và "smth". Dành thời gian để đánh vần chính xác, cho dễ đọc.
Tin Man

0

Đối với những người có bố cục trung tâm (thông qua margin:0 auto;), đây là bản tổng hợp của position:fixedgiải pháp cùng với giải pháp được đề xuất của @tfe .

Sử dụng giải pháp này nếu bạn gặp phải tình trạng giật trang (do thanh cuộn hiển thị / ẩn).

// lock scroll position, but retain settings for later
var scrollPosition = [
    window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
    window.pageYOffset || document.documentElement.scrollTop  || document.body.scrollTop
];
var $html = $('html'); // bow to the demon known as MSIE(v7)
$html.addClass('modal-noscroll');
$html.data('scroll-position', scrollPosition);
$html.data('margin-top', $html.css('margin-top'));
$html.css('margin-top', -1 * scrollPosition[1]);

…kết hợp với…

// un-lock scroll position
var $html = $('html').removeClass('modal-noscroll');
var scrollPosition = $html.data('scroll-position');
var marginTop = $html.data('margin-top');
$html.css('margin-top', marginTop);
window.scrollTo(scrollPosition[0], scrollPosition[1])

... và cuối cùng, CSS cho .modal-noscroll...

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

Tôi muốn mạo hiểm nói rằng đây là một sửa chữa thích hợp hơn bất kỳ giải pháp nào khác ngoài đó, nhưng tôi chưa thử nghiệm nó một cách triệt để.


Chỉnh sửa: xin lưu ý rằng tôi không biết điều này có thể thực hiện tồi tệ như thế nào (đọc: nổ tung) trên một thiết bị cảm ứng.


0

Bạn cũng có thể sử dụng DOM để làm như vậy. Giả sử bạn có một chức năng bạn gọi như thế này:

function disable_scroll() {
document.body.style.overflow="hidden";
}

Và đó là tất cả để có nó! Hy vọng điều này sẽ giúp ngoài các câu trả lời khác!


0

Đây là những gì tôi đã làm:

CoffeeScript:

    $("input").focus ->
        $("html, body").css "overflow-y","hidden"
        $(document).on "scroll.stopped touchmove.stopped mousewheel.stopped", (event) ->
            event.preventDefault()

    $("input").blur ->
        $("html, body").css "overflow-y","auto"
        $(document).off "scroll.stopped touchmove.stopped mousewheel.stopped"

Javascript:

$("input").focus(function() {
 $("html, body").css("overflow-y", "hidden");
 $(document).on("scroll.stopped touchmove.stopped mousewheel.stopped", function(event) {
   return event.preventDefault();
 });
});

$("input").blur(function() {
 $("html, body").css("overflow-y", "auto");
 $(document).off("scroll.stopped touchmove.stopped mousewheel.stopped");
});

0

Không chắc chắn nếu có ai đã thử giải pháp của tôi. Cái này hoạt động trên toàn bộ cơ thể / html nhưng không nghi ngờ gì nó có thể được áp dụng cho bất kỳ yếu tố nào phát sinh sự kiện cuộn.

Chỉ cần đặt và bỏ cuộn scrollLock khi bạn cần.

var scrollLock = false;
var scrollMem = {left: 0, top: 0};

$(window).scroll(function(){
    if (scrollLock) {
        window.scrollTo(scrollMem.left, scrollMem.top);
    } else {
        scrollMem = {
            left: self.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
            top: self.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
        };
    }
});

Dưới đây là ví dụ về JSFiddle

Hy vọng điều này sẽ giúp ai đó.


Điều này hoạt động như nó cần, với một ngoại lệ. Khi cuộn bị khóa và tôi cuộn, nó hơi co giật một chút, trước khi thực sự khóa cuộn ...
Thomas Teilmann

0

Tôi nghĩ rằng giải pháp tốt nhất và sạch sẽ là:

window.addEventListener('scroll',() => {
    var x = window.scrollX;
    var y = window.scrollY;
    window.scrollTo(x,y);
});

Và với jQuery:

$(window).on('scroll',() => {
    var x = window.scrollX;
    var y = window.scrollY;
    window.scrollTo(x,y)
})

Những người nghe sự kiện nên chặn cuộn. Chỉ cần loại bỏ chúng để kích hoạt lại cuộn

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.