Como desativar programaticamente a rolagem de páginas com o jQuery

163

Usando o jQuery, gostaria de desativar a rolagem do corpo:

Minha ideia é:

  1. Conjunto body{ overflow: hidden;}
  2. Capturar a corrente scrollTop();/scrollLeft()
  3. Associe-se ao evento de rolagem do corpo, defina scrollTop / scrollLeft para o valor capturado.

Existe uma maneira melhor?


Atualizar:

Por favor, veja meu exemplo e um motivo para, em http://jsbin.com/ikuma4/2/edit

Estou ciente de que alguém estará pensando "por que ele não usa apenas position: fixedno painel?".

Por favor, não sugira isso, pois tenho outros motivos.

Hailwood
fonte
7
"Existe uma maneira melhor?" - além de permitir que o navegador se comporte normalmente?
Fenton
22
"melodramaticamente"?
Mike Weller
6
Talvez significou programaticamente? Uma vez que é o topo ortográfico sugestão de correção firefox para 'programaticamente'
Michael Shimmins
4
Esta thread vai \ b \
Cipi
3
! @Sohnee incapacitante rolagem == ruim
Mansiemans

Respostas:

136

A única maneira que encontrei para fazer isso é semelhante ao que você descreveu:

  1. Pegue a posição atual de rolagem (não se esqueça do eixo horizontal!).
  2. Defina o estouro como oculto (provavelmente deseja manter o valor anterior do estouro).
  3. Role o documento para a posição de rolagem armazenada com scrollTo ().

Então, quando estiver pronto para permitir a rolagem novamente, desfaça tudo isso.

Edit: nenhuma razão eu não posso lhe dar o código desde que me dei ao trabalho de desenterrá-lo ...

// 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
fonte
2
consulte jsbin.com/ikuma4/2/edit e explique-me alguma razão para que a sua seja melhor? estou faltando alguma coisa (i perguntar como eu não vejo qualquer razão para a duração da sua resposta, em comparação com o meu exemplo)
Hailwood
3
Sua abordagem não funciona no IE7. Eu tentei isso primeiro também. O problema é que ele não reage ao evento de rolagem com rapidez suficiente. Ele permite que o documento role, depois o encaixe novamente quando seu JS redefinir a posição de rolagem de volta para onde você desejar.
tfe
1
Além disso, se o corpo tivesse um transbordamento de algo diferente auto, ele seria substituído. Eu precisava preservar a configuração existente, o que também adiciona alguma sobrecarga.
tfe
Alguém sabe por que simplesmente estilizar htmle bodycom overflow: hiddené insuficiente? Ainda acabamos precisando do manipulador de eventos.
22411 kpozin
4
Esta é uma resposta fantástica. E para fazê-lo funcionar em dispositivos sensíveis ao toque, confira esta resposta.
28413 Patrick Patrick
235

Isso desativará completamente a rolagem:

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

Restaurar:

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

Testei no Firefox e Chrome.

gitaarik
fonte
18
funciona como esperado. Obrigado! Esta deveria ter sido a resposta aceita!
Dave Chen
6
Ainda rola com o botão do meio do mouse no chrome.
Lothar
16
Isso perde a posição atual de rolagem. O OP mencionou explicitamente sobre a captura da posição de rolagem, então presumo que ele exigisse isso. De qualquer forma, eu preciso, portanto, este é de uso limitado para mim
zerm
7
Omitir o PS height: 100%efetivamente bloqueia a rolagem na posição atual sem pular - no Chrome mais recente, pelo menos.
Zerm 26/11/2013
2
Esta não é a resposta correta. Posição de rolagem não é capturado
taylorcressy
43

tente isso

$('#element').on('scroll touchmove mousewheel', function(e){
  e.preventDefault();
  e.stopPropagation();
  return false;
})
cubbiu
fonte
exatamente o que eu estava procurando ... quase. De qualquer forma, para desativá-lo durante as teclas de seta?
Cody
2
@Cody - combine isso com css overflow: hidden
Darius.V
2
@cubbiu como reverter isso?
Meer
3
Você pode usar$('#element').off('scroll touchmove mousewheel');
arnuschky
1
Ótima solução. Embora como você desabilite a bodyrolagem apenas e permita a rolagem dentro de outros elementos filhos que possuem overflow: scroll?
Fizzix 18/04
27

Eu apenas forneço um pouco de ajuste para a solução por tfe . Em particular, adicionei algum controle adicional para garantir que não haja mudança no conteúdo da página (também conhecida como mudança de página ) quando a barra de rolagem estiver definida como hidden.

Duas funções Javascript lockScroll()e unlockScroll()podem ser definidas, respectivamente, para bloquear e desbloquear a rolagem da página.

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

onde eu assumi que o <body>não tem margem inicial.

Observe que, embora a solução acima funcione na maioria dos casos práticos, ela não é definitiva, pois precisa de mais personalização para páginas que incluem, por exemplo, um cabeçalho com position:fixed. Vamos entrar neste caso especial com um exemplo. Suponha que você tenha

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

com

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

Em seguida, deve-se adicionar o seguinte em funções lockScroll()e unlockScroll():

function lockScroll(){
    //Omissis   


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

function unlockScroll(){
    //Omissis   

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

Por fim, cuide de algum possível valor inicial para as margens ou forros.

Jean Valjean
fonte
4
Você tem um erro no seu javascript $ body.css ({'margin-right': 0, 'margin-bottom', 0}); deve ser $ body.css ({'margin-right': 0, 'margin-bottom': 0});
9788 Johansrk #
Na verdade, é só usar marginRighte marginLeft:)
Martijn
25

você pode usar este código:

$("body").css("overflow", "hidden");
mr.soroush
fonte
8
Você ainda pode usar o botão do meio do mouse para rolar.
Roger Far
2
Não, está tudo bem e sem rolagem com isso!
mr.soroush
Se você usa algum CSS extra, PODE desativar completamente a rolagem, veja minha resposta para mais detalhes.
gitaarik
21

Para desativar a rolagem, tente o seguinte:

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

reiniciar:

$(window).off('scroll');
Patrick DaVader
fonte
Esta foi uma solução fantástica para o que eu precisava.
Terry Carter
@EveryScreamer não, faz a tela tremer como um louco. Tentando encontrar uma solução alternativa.
Telarian
5

Eu escrevi um plugin jQuery para lidar com isso: $ .disablescroll .

Impede a rolagem dos eventos de roda do mouse, movimento de toque e pressionamento de tecla, como Page Down.

Há uma demonstração aqui .

Uso:

$(window).disablescroll();

// To re-enable scrolling:
$(window).disablescroll("undo");
Josh Harrison
fonte
Tentei usar o plug-in disablescroll () para desativar temporariamente a rolagem ao ouvir o evento mouswheel / scroll, mas não funciona. Alguma chance de você conhecer uma maneira de conseguir esse efeito?
yellow-saint
@JB Eu provavelmente posso ajudar, mas os comentários não são o melhor lugar. Junte-se a mim neste bate-papo de estouro de pilha e eu vou ver o que posso fazer: chat.stackoverflow.com/rooms/55043/disablescroll-usage
Josh Harrison
Sinto muito, mas este plugin nem funciona no seu jsfiddle.
markj
Você pode me ajudar a inspecionar isso dizendo-me em qual navegador / plataforma ele parece não funcionar, por favor?
Josh Harrison
5

Você pode anexar uma função para rolar eventos e impedir seu comportamento padrão.

var $window = $(window);

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

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

https://jsfiddle.net/22cLw9em/

dzimi
fonte
1
Esta é a resposta certa. Não sei por que não está definido como ele
Guilherme Ferreira
Funciona. Só precisa o código de reset publicado para coincidir com resposta Patricks
Hastig Zusammenstellen
4

Um revestimento para desativar a rolagem, incluindo o botão do meio do mouse.

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

edit : De qualquer maneira, não é necessário jQuery, abaixo do mesmo que o vanilla JS (isso significa que não há estruturas, apenas JavaScript):

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

this.documentElement.scrollTop - padrão

this.body.scrollTop - compatibilidade com o IE

Pawel
fonte
4
  • Para ocultar a rolagem: $("body").css("overflow", "hidden");
  • Para restaurar a rolagem: $("body").css("overflow", "initial");
Joan Alberto Aguilar Peña
fonte
3

Você não pode simplesmente definir a altura do corpo para 100% e o estouro oculto? Consulte http://jsbin.com/ikuma4/13/edit

Adrian Schmidt
fonte
$ ("html"). css ({height: '100%', estouro: 'oculto'}); Ele simplesmente funciona, obrigado Adrian
Alexey
3

Alguém postou esse código, que tem o problema de não manter a posição de rolagem quando restaurada. A razão é que as pessoas tendem a aplicá-lo ao html e ao corpo ou apenas ao corpo, mas devem ser aplicadas apenas ao html. Dessa forma, quando restaurada, a posição de rolagem será mantida:

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

Restaurar:

$('html').css({
    'overflow': 'auto',
    'height': 'auto'
});
Mescalina
fonte
não 'overflow': 'auto',use'overflow': 'initial',
evtuhovdo 10/09/19
2

Isso pode ou não funcionar para seus propósitos, mas você pode estender o jScrollPane para disparar outras funcionalidades antes que ele faça sua rolagem. Acabei de testar isso um pouco, mas posso confirmar que você pode pular e impedir a rolagem completamente. Tudo o que fiz foi:

  • Faça o download do zip da demo: http://github.com/vitch/jScrollPane/archives/master
  • Abra a demonstração "Eventos" (events.html)
  • Edite-o para usar a fonte de script não minificada: <script type="text/javascript" src="script/jquery.jscrollpane.js"></script>
  • No jquery.jscrollpane.js, insira um "return"; na linha 666 (número auspicioso da linha! mas, caso sua versão seja um pouco diferente, esta é a primeira linha da positionDragY(destY, animate)função

Inicie o events.html e você verá uma caixa de rolagem normalmente que, devido à sua intervenção de codificação, não será rolada.

Você pode controlar as barras de rolagem do navegador inteiro dessa maneira (consulte fullpage_scroll.html).

Portanto, presumivelmente, o próximo passo é adicionar uma chamada a alguma outra função que apaga e faz sua mágica de ancoragem, e decide se deve continuar com o pergaminho ou não. Você também tem chamadas de API para definir scrollTop e scrollLeft.

Se você quiser mais ajuda, poste onde quiser!

Espero que isso tenha ajudado.

Jeremy Warne
fonte
2

Coloquei uma resposta que pode ajudar aqui: jQuery simplemodal desativar rolagem

Ele mostra como desativar as barras de rolagem sem mudar o texto. Você pode ignorar as partes sobre simplemodal.

mhenry1384
fonte
1

Se você quiser apenas desabilitar a rolagem com a navegação pelo teclado, poderá substituir o evento de pressionamento de tecla.

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

Tente este código:

    $(function() { 
        // ...

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

        // ...
    });
Jopie
fonte
0

Você pode encobrir a janela com uma div rolável para impedir a rolagem do conteúdo em uma página. E, ocultando e mostrando, você pode bloquear / desbloquear seu pergaminho.

Faça algo parecido com isto:

#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
fonte
7
Por favor, não use abreviações como "u" e "smth". Aproveite o tempo para escrever corretamente, para facilitar a leitura.
the Tin Man
0

Para as pessoas que centralizaram os layouts (via margin:0 auto;), aqui está um mash-up da position:fixedsolução, juntamente com a solução proposta pela @tfe .

Use esta solução se você estiver enfrentando o snap da página (devido à barra de rolagem que mostra / oculta).

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

…combinado com…

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

… E, finalmente, o CSS para .modal-noscroll

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

Atrevo-me a dizer que este é mais de uma correção adequada do que qualquer das outras soluções lá fora, mas eu não testei que ainda completamente ...: P


Editar: observe que não tenho idéia do quanto isso pode ser ruim (leia-se: explodir) em um dispositivo de toque.

Matthemattics
fonte
0

Você também pode usar o DOM para fazer isso. Digamos que você tenha uma função que você chama assim:

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

E é só isso! Espero que isso ajude, além de todas as outras respostas!

Brendan
fonte
0

Isto é o que acabei fazendo:

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
fonte
0

Não tenho certeza se alguém já experimentou minha solução. Este funciona em todo o corpo / html, mas sem dúvida pode ser aplicado a qualquer elemento que dispara um evento de rolagem.

Basta definir e desabilitar o scrollLock conforme necessário.

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

Aqui está o exemplo JSFiddle

Espero que este ajude alguém.

FossilMFC
fonte
Este funciona como deveria, com uma exceção. Quando o rolo está bloqueado, e eu rolar, ele contrai meio um pouco, antes de realmente trancar a rolagem ...
Thomas Teilmann
0

Eu acho que a melhor solução e limpa é:

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

E com o jQuery:

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

O ouvinte de eventos deve bloquear a rolagem. Basta removê-los para reativar a rolagem

Tiziano
fonte