Jak programowo wyłączyć przewijanie stron za pomocą jQuery

163

Korzystając z jQuery, chciałbym wyłączyć przewijanie treści:

Mój pomysł to:

  1. Zestaw body{ overflow: hidden;}
  2. Uchwyć prąd scrollTop();/scrollLeft()
  3. Powiązanie ze zdarzeniem body scroll, ustaw scrollTop / scrollLeft na przechwyconą wartość.

Czy jest lepszy sposób?


Aktualizacja:

Proszę zobaczyć mój przykład i powód, dla którego jest to http://jsbin.com/ikuma4/2/edit

Wiem, że ktoś pomyśli „dlaczego nie używa po prostu position: fixedna panelu?”.

Nie sugeruj tego, bo mam inne powody.

Hailwood
źródło
7
"Czy jest lepszy sposób?" - inne niż pozwalanie przeglądarce na normalne działanie?
Fenton,
22
„melodramatycznie”?
Mike Weller,
6
Może chodziło o programowo? Ponieważ jest to najlepsza propozycja korekty pisowni w przeglądarce Firefox dla „programowo”
Michael Shimmins
4
Ten wątek będzie \ b \
Cipi,
3
@Sohnee wyłącza przewijanie! == bad
Mansiemans

Odpowiedzi:

136

Jedyny sposób, w jaki to zrobiłem, jest podobny do tego, co opisałeś:

  1. Chwyć aktualną pozycję przewijania (nie zapomnij o osi poziomej!).
  2. Ustaw przepełnienie na ukryte (prawdopodobnie chcesz zachować poprzednią wartość przepełnienia).
  3. Przewiń dokument do zapisanej pozycji przewijania za pomocą scrollTo ().

Następnie, gdy będziesz gotowy, aby ponownie zezwolić na przewijanie, cofnij to wszystko.

Edycja: nie ma powodu, dla którego nie mogę podać kodu, ponieważ zadałem sobie trud, aby go wykopać ...

// 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])
tfe
źródło
2
zobacz jsbin.com/ikuma4/2/edit i wyjaśnij mi powód, dla którego twój jest lepszy? czy coś mi brakuje (pytam, ponieważ nie widzę żadnego powodu długości Twojej odpowiedzi w porównaniu z moim przykładem)
Hailwood
3
Twoje podejście nie działa w IE7. Ja też tego spróbowałem. Problem polega na tym, że nie reaguje wystarczająco szybko na zdarzenie przewijania. Pozwala przewijać dokument, a następnie cofa go, gdy JS resetuje pozycję przewijania z powrotem tam, gdzie chcesz.
tfe
1
Ponadto, jeśli w treści pojawiło się coś innego niż treść auto, zostanie ono nadpisane. Musiałem zachować istniejące ustawienie, więc to również zwiększa koszty.
tfe
Czy ktoś wie, dlaczego samo stylizowanie htmli za bodypomocą overflow: hiddenjest niewystarczające? Nadal potrzebujemy obsługi zdarzeń.
kpozin
4
To fantastyczna odpowiedź. Aby działał na urządzeniach dotykowych, zapoznaj się z odpowiedzią.
Patrick
235

Spowoduje to całkowite wyłączenie przewijania:

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

Przywrócić:

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

Przetestowałem to na Firefoksie i Chrome.

gitaarik
źródło
18
działa zgodnie z oczekiwaniami. Dzięki! To powinna być zaakceptowana odpowiedź!
Dave Chen
6
Nadal przewija się środkowym przyciskiem myszy na chrome.
Lothar
16
Spowoduje to utratę aktualnej pozycji przewijania. OP wyraźnie wspomniał o przechwytywaniu pozycji przewijania, więc zakładam, że tego wymagał. W każdym razie tego potrzebuję, więc ma to dla mnie ograniczone zastosowanie
zerm
7
PS Pominięcie height: 100%efektywnie blokuje przewijanie w aktualnej pozycji bez skakania - przynajmniej na najnowszym Chrome.
zerm
2
To NIE jest poprawna odpowiedź. Pozycja przewijania nie została uchwycona
taylorcressy
43

Spróbuj tego

$('#element').on('scroll touchmove mousewheel', function(e){
  e.preventDefault();
  e.stopPropagation();
  return false;
})
cubbiu
źródło
właśnie tego szukałem ... prawie. W każdym razie, aby wyłączyć go podczas klawiszy strzałek?
Cody,
2
@Cody - połącz to z przepełnieniem css: hidden
Darius.V
2
@cubbiu jak to odwrócić?
Meer
3
Możesz skorzystać$('#element').off('scroll touchmove mousewheel');
arnuschky
1
Świetne rozwiązanie. Chociaż jak wyłączyć bodyprzewijanie, a jednocześnie zezwolić na przewijanie w obrębie innych elementów podrzędnych, które mają overflow: scroll?
Fizzix
27

Podaję tylko małe dostrojenie rozwiązania przez tfe . W szczególności dodałem dodatkową kontrolę, aby upewnić się, że nie ma przesunięcia zawartości strony (czyli przesunięcia strony ), gdy pasek przewijania jest ustawiony na hidden.

Dwie funkcje JavaScript lockScroll()i unlockScroll()można zdefiniować odpowiednio, aby zablokować i odblokować przewijanie strony.

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

gdzie założyłem, że <body>nie ma początkowego depozytu zabezpieczającego.

Zauważ, że chociaż powyższe rozwiązanie działa w większości praktycznych przypadków, nie jest ostateczne, ponieważ wymaga dalszego dostosowania dla stron, które zawierają na przykład nagłówek z position:fixed. Przejdźmy do tego szczególnego przypadku z przykładem. Przypuśćmy, że tak

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

z

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

Następnie należałoby dodać następujących funkcji lockScroll()oraz unlockScroll():

function lockScroll(){
    //Omissis   


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

function unlockScroll(){
    //Omissis   

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

Na koniec zwróć uwagę na możliwą wartość początkową marginesów lub wypełnień.

Jean Valjean
źródło
4
Masz błąd w swoim javascript $ body.css ({'margin-right': 0, 'margin-bottom', 0}); powinno być $ body.css ({'margin-right': 0, 'margin-bottom': 0});
Johansrk
Właściwie po prostu użyj marginRighti marginLeft:)
Martijn
25

możesz użyć tego kodu:

$("body").css("overflow", "hidden");
pan Soroush
źródło
8
Nadal możesz używać środkowego przycisku myszy do przewijania.
Roger Far
2
Nie, to jest w porządku i nie ma z tym przewijania!
mr.soroush
Jeśli używasz dodatkowego CSS, MOŻESZ całkowicie wyłączyć przewijanie, zobacz moją odpowiedź, aby uzyskać więcej informacji.
gitaarik
21

Aby wyłączyć przewijanie, spróbuj tego:

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

zresetować:

$(window).off('scroll');
Patrick DaVader
źródło
To było fantastyczne rozwiązanie na to, czego potrzebowałem.
Terry Carter
@EveryScreamer nie, to sprawia, że ​​ekran drży jak szalony. Próbuję znaleźć obejście.
Telarian
5

Napisałem wtyczkę jQuery do obsługi tego: $ .disablescroll .

Zapobiega przewijaniu w przypadku zdarzeń związanych z kółkiem myszy, ruchem dotykowym i naciśnięciem klawisza, takich jak Page Down.

Tutaj jest demo .

Stosowanie:

$(window).disablescroll();

// To re-enable scrolling:
$(window).disablescroll("undo");
Josh Harrison
źródło
Próbowałem użyć twojej wtyczki disablescroll (), aby tymczasowo wyłączyć przewijanie po usłyszeniu zdarzenia kółka myszy / przewijania, ale to nie działa. Czy znasz sposób na osiągnięcie tego efektu?
żółty święty
@JB Prawdopodobnie mogę pomóc, ale komentarze nie są najlepszym miejscem. Dołącz do mnie na czacie o przepełnieniu stosu, a zobaczę, co mogę zrobić: chat.stackoverflow.com/rooms/55043/disablescroll-usage
Josh Harrison.
Przepraszam, ale ta wtyczka nie działa nawet w twoim jsfiddle.
markj
Możesz mi pomóc w sprawdzeniu tego, mówiąc mi, w której przeglądarce / platformie nie działa?
Josh Harrison
5

Możesz dołączyć funkcję do przewijania zdarzeń i zapobiegania jej domyślnemu zachowaniu.

var $window = $(window);

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

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

https://jsfiddle.net/22cLw9em/

dzimi
źródło
1
To jest właściwa odpowiedź. Nie wiem, dlaczego nie jest ustawione tak, jak jest
Guilherme Ferreira
To działa. Wystarczy wysłany kod resetowania, aby dopasować odpowiedź Patricksa
Hastig Zusammenstellen
4

Jedna linijka wyłączająca przewijanie, w tym środkowy przycisk myszy.

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

edycja : i tak nie ma potrzeby korzystania z jQuery, poniżej to samo co powyżej w waniliowym JS (to znaczy bez frameworków, tylko JavaScript):

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

this.documentElement.scrollTop - standard

this.body.scrollTop - zgodność z IE

Paweł
źródło
4
  • Aby ukryć przewijanie: $("body").css("overflow", "hidden");
  • Aby przywrócić przewijanie: $("body").css("overflow", "initial");
Joan Alberto Aguilar Peña
źródło
3

Nie możesz po prostu ustawić wysokości ciała na 100% i ukryć przelewu? Zobacz http://jsbin.com/ikuma4/13/edit

Adrian Schmidt
źródło
$ ("html"). css ({wysokość: '100%', przepełnienie: 'ukryte'}); Po prostu działa, dziękuję Adrian
Alexey
3

Ktoś wysłał ten kod, który ma problem z nie zachowaniem pozycji przewijania po przywróceniu. Powodem jest to, że ludzie zwykle stosują go do html i body lub tylko do body, ale powinien być stosowany tylko do html. W ten sposób po przywróceniu pozycja przewijania zostanie zachowana:

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

Przywrócić:

$('html').css({
    'overflow': 'auto',
    'height': 'auto'
});
Mescalina
źródło
nie 'overflow': 'auto',używać'overflow': 'initial',
evtuhovdo
2

Może to działać lub nie do Twoich celów, ale możesz rozszerzyć jScrollPane, aby uruchomić inne funkcje, zanim wykona przewijanie. Tylko trochę to przetestowałem, ale mogę potwierdzić, że możesz wskoczyć i całkowicie zapobiec przewijaniu. Wszystko co zrobiłem to:

  • Pobierz plik demonstracyjny ZIP: http://github.com/vitch/jScrollPane/archives/master
  • Otwórz demo „Wydarzenia” (events.html)
  • Edytuj go, aby użyć niezminifikowanego źródła skryptu: <script type="text/javascript" src="script/jquery.jscrollpane.js"></script>
  • Wewnątrz jquery.jscrollpane.js wstaw „return”; w linii 666 (pomyślny numer linii! ale w przypadku, gdy twoja wersja różni się nieznacznie, jest to pierwsza linia positionDragY(destY, animate)funkcji

Uruchom events.html, a zobaczysz normalnie przewijane okienko, które z powodu interwencji w kodowanie nie będzie się przewijać.

W ten sposób możesz kontrolować wszystkie paski przewijania przeglądarki (patrz fullpage_scroll.html).

Więc prawdopodobnie następnym krokiem jest dodanie wywołania do innej funkcji, która uruchamia się i wykonuje magię zakotwiczenia, a następnie decyduje, czy kontynuować przewijanie, czy nie. Masz również wywołania API do ustawiania scrollTop i scrollLeft.

Jeśli chcesz uzyskać więcej pomocy, napisz, do czego zmierzasz!

Mam nadzieję, że to pomogło.

Jeremy Warne
źródło
2

Tutaj umieściłem odpowiedź, która może pomóc: jQuery simplemodal wyłącz przewijanie

Pokazuje, jak wyłączyć paski przewijania bez przesuwania tekstu. Możesz zignorować fragmenty dotyczące simplemodal.

mhenry1384
źródło
1

Jeśli chcesz tylko wyłączyć przewijanie za pomocą nawigacji za pomocą klawiatury, możesz zastąpić zdarzenie keydown.

$(document).on('keydown', function(e){
    e.preventDefault();
    e.stopPropagation();
});
Sean
źródło
1

Wypróbuj ten kod:

    $(function() { 
        // ...

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

        // ...
    });
Jopie
źródło
0

Możesz zakryć okno przewijalnym elementem div, aby zapobiec przewijaniu zawartości strony. A ukrywając i pokazując, możesz zablokować / odblokować zwój.

Zrób coś takiego:

#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();
}
Appex
źródło
7
Nie używaj skrótów, takich jak „u” i „coś”. Poświęć trochę czasu na poprawną pisownię, aby była czytelna.
Tin Man
0

Dla osób, które mają wyśrodkowane układy (przez margin:0 auto;), oto połączenie position:fixedrozwiązania wraz z proponowanym rozwiązaniem @tfe .

Skorzystaj z tego rozwiązania, jeśli występuje przyciąganie stron (ze względu na wyświetlanie / ukrywanie paska przewijania).

// 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]);

…w połączeniu z…

// 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])

… I wreszcie CSS dla .modal-noscroll

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

Zaryzykowałbym stwierdzenie, że jest to bardziej właściwe rozwiązanie niż jakiekolwiek inne dostępne rozwiązania, ale nie przetestowałem go jeszcze tak dokładnie…: P


Edycja: pamiętaj, że nie mam pojęcia, jak źle może to działać (czytaj: wysadzić) na urządzeniu dotykowym.

Matematyka
źródło
0

Możesz także użyć do tego DOM. Powiedzmy, że masz funkcję, którą nazywasz w ten sposób:

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

I to wszystko! Mam nadzieję, że to pomoże oprócz wszystkich innych odpowiedzi!

Brendan
źródło
0

Oto, co ostatecznie zrobiłem:

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");
});
Marz
źródło
0

Nie jestem pewien, czy ktoś wypróbował moje rozwiązanie. Ten działa na całym body / html, ale bez wątpienia można go zastosować do dowolnego elementu, który uruchamia zdarzenie przewijania.

Po prostu włącz i wyłącz scrollLock, jeśli potrzebujesz.

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

Oto przykład JSFiddle

Mam nadzieję, że ten komuś pomoże.

FossilMFC
źródło
Ten działa tak, jak powinien, z jednym wyjątkiem. Kiedy zwój jest zablokowany, a ja przewijam, trochę drga, zanim faktycznie
zablokuje
0

Myślę, że najlepszym i czystym rozwiązaniem jest:

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

A z jQuery:

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

Ten detektor zdarzeń powinien blokować przewijanie. Po prostu je usuń, aby ponownie włączyć przewijanie

Tiziano
źródło