Role até o final da div?

808

Estou criando um bate-papo usando solicitações de ajax em trilhos e estou tentando fazer com que um div role para baixo sem muita sorte.

Estou embrulhando tudo nesta div:

#scroll {
    height:400px;
    overflow:scroll;
}

Existe uma maneira de mantê-lo rolado até o final por padrão usando JS?

Existe uma maneira de mantê-lo rolado para baixo depois de uma solicitação do ajax?

dMix
fonte

Respostas:

1325

Aqui está o que eu uso no meu site:

var objDiv = document.getElementById("your_div");
objDiv.scrollTop = objDiv.scrollHeight;
Jeremy Ruten
fonte
13
este método está correto em todos os navegadores?
Jondinham #
1
@PaulDinh: Acabei de analisar isso e há um problema no IE7 e inferior usando o scrollHeight. Parece haver uma solução alternativa para o IE7 aqui .
18712 Sean
3
Por que não funciona após anexar dinamicamente elementos dentro da div?
Vince
3
@Vince - É um acordo único. Se você alterar o conteúdo, precisará executar novamente. O comando basicamente diz "mova a barra de rolagem para esta posição".
DrFriedParts
8
Além disso, se você tiver elementos colocados dentro de uma div, por exemplo, poderá rolar um elemento específico para exibição. (ou seja, o elemento é visível dentro da div pai) .. assim: $ ("#" + instanceID) .scrollTop ($ ("#" + instanceID) [0] .scrollIntoView);
netfed
360

Isso é muito mais fácil se você estiver usando o jQuery scrollTop :

$("#mydiv").scrollTop($("#mydiv")[0].scrollHeight);
andsien
fonte
273
Como isso é mais fácil?
Captainspi
78
1 linha em vez de 2? nenhuma pista, mas o que você pode fazer facilmente com o JQuery é animar a ação da seguinte maneira: $ ("# div-id"). animate ({scrollTop: $ ("# div-id") [0] .crollHeight}, 1000 ); espero que isso ajude alguém :)
Samuel
28
Você precisa [0] para obter elemento DOM do elemento jQuery para obter scrollHeight
Jimmy Bosse
14
"Sem mencionar que o JQ é mais difícil de ler / entender!" Puramente uma opinião. Por exemplo, acho o JQuery muito mais fácil de ler, entender e fazer coisas. E essa solução é melhor se você já estiver usando o JQuery de qualquer maneira.
21713 Hanna
47
Sem se repetir:$("#mydiv").scrollTop(function() { return this.scrollHeight; });
Eric
98

Você pode usar o seguinte código:

function scrollToBottom (id) {
   var div = document.getElementById(id);
   div.scrollTop = div.scrollHeight - div.clientHeight;
}

Para executar uma rolagem suave com o JQuery:

function scrollSmoothToBottom (id) {
   var div = document.getElementById(id);
   $('#' + id).animate({
      scrollTop: div.scrollHeight - div.clientHeight
   }, 500);
}

Veja o exemplo no JSFiddle

Eis por que isso funciona:

insira a descrição da imagem aqui

Ref: scrollTop , scrollHeight , clientHeight

Tho
fonte
92

usando o jQuery animate :

$('#DebugContainer').stop().animate({
  scrollTop: $('#DebugContainer')[0].scrollHeight
}, 800);
DadViegas
fonte
5
Foi o que Sam disse neste comentário . É provavelmente mais útil em uma resposta real!
Quentin Pradet
6
Observe como esta resposta usa .stop () , o que evita problemas com várias animações.
kalyfe
Surpreendentemente, este é o único que funciona para mim em todas as respostas anteriores. Pode ser por causa de como meus outros divs são criadas em torno da camada que precisa manter a rolagem
Duniyadnd
Este foi o único que trabalhou para mim (eu estou adicionando imagens, não texto)
john ktejik
36
var mydiv = $("#scroll");
mydiv.scrollTop(mydiv.prop("scrollHeight"));

Trabalhos do jQuery 1.6

https://api.jquery.com/scrollTop/

http://api.jquery.com/prop/

Akira Yamamoto
fonte
1
Essa solução funciona para elementos com uma classe CSS exclusiva e ainda sem ID de CSS. A solução do comentário principal não funciona pronta para uso com uma classe CSS.
CFitz 5/02/19
31

Método mais recente que funciona em todos os navegadores atuais :

this.scrollIntoView(false);
tnt-rox
fonte
1
Acho que isso só funciona no firefox: developer.mozilla.org/en/docs/Web/API/Element/…
Amrit Kahlon
3
O suporte realmente está faltando no atm, mas se isso for aceito, seria incrível.
21330 Kristjan Liiva
Alguma atualização? Eu sinto que isso deve ser aceito como a boa resposta. Quero dizer, vamos lá jQuery?
precisa saber é
trabalhando: document.querySelector (". lista mdl"). scrollIntoView (false);
Johann Medina
15

rolagem suave com Javascript:

document.getElementById('messages').scrollIntoView({ behavior: 'smooth', block: 'end' });

adl
fonte
8

Se você não quiser confiar scrollHeight, o seguinte código ajuda:

$('#scroll').scrollTop(1000000);
Benny Neugebauer
fonte
1
Nenhuma das soluções acima, incluindo a sua, parece funcionar no Firefox no Android ... alguma opinião, por favor?
Kaya Toast
Não importa, eu estava usando um número muito grande ( 1E10). Um número menor funciona
andrewtweber 22/11/2015
Sempre importa
Ben Taliadoros
4
Por que seria um desempenho ruim? Não é como se estivesse iterando sobre cada pixel. Agora más práticas são outra questão ...
devios1 30/03
$ ('# scroll'). scrollTop (Infinity), isso também deve funcionar.
Madhav Poudel 18/05/19
5

Usando jQuery, scrollTop é usado para definir a posição vertical da barra de rolagem para qualquer elemento. há também um bom plugin jquery scrollTo usado para rolar com animação e opções diferentes ( demos )

var myDiv = $("#div_id").get(0);
myDiv.scrollTop = myDiv.scrollHeight;

se você quiser usar o método de animação do jQuery para adicionar animação enquanto estiver rolando para baixo, verifique o seguinte trecho:

var myDiv = $("#div_id").get(0);
myDiv.animate({
    scrollTop: myDiv.scrollHeight
  }, 500);
Muhammad Soliman
fonte
4

Eu encontrei o mesmo problema, mas com uma restrição adicional: eu não tinha controle sobre o código que anexava novos elementos ao contêiner de rolagem. Nenhum dos exemplos que encontrei aqui me permitiu fazer exatamente isso. Aqui está a solução que eu acabei com.

Ele usa Mutation Observers( https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver ) que o torna utilizável apenas em navegadores modernos (embora existam polyfills)

Então, basicamente, o código faz exatamente isso:

var scrollContainer = document.getElementById("myId");

// Define the Mutation Observer
var observer = new MutationObserver(function(mutations) {

  // Compute sum of the heights of added Nodes
  var newNodesHeight = mutations.reduce(function(sum, mutation) {
      return sum + [].slice.call(mutation.addedNodes)
        .map(function (node) { return node.scrollHeight || 0; })
        .reduce(function(sum, height) {return sum + height});
  }, 0);

  // Scroll to bottom if it was already scrolled to bottom
  if (scrollContainer.clientHeight + scrollContainer.scrollTop + newNodesHeight + 10 >= scrollContainer.scrollHeight) {
    scrollContainer.scrollTop = scrollContainer.scrollHeight;
  }

});

// Observe the DOM Element
observer.observe(scrollContainer, {childList: true});

Fiz um violino para demonstrar o conceito: https://jsfiddle.net/j17r4bnk/

Benkinass
fonte
como obter id dinâmico? Como <div class="abc"><div data-bind=attr : {'id': myId } ></div></div>neste código, myId é uma variável. Como posso acessar esse id no script.
Irfan Yusanif
Não tenho muita certeza de entender sua pergunta. No meu exemplo, "myId" é o ID do contêiner de rolagem. Deseja criar mais de uma área na qual o usuário possa rolar?
21915 Benkinass
4

Javascript ou jquery:

var scroll = document.getElementById('messages');
   scroll.scrollTop = scroll.scrollHeight;
   scroll.animate({scrollTop: scroll.scrollHeight});

Css:

 .messages
 {
      height: 100%;
      overflow: auto;
  }
Lay Leangsros
fonte
4

Achei isso realmente útil, obrigado.

Para o pessoal do Angular 1.X por aí:

angular.module('myApp').controller('myController', ['$scope', '$document',
  function($scope, $document) {

    var overflowScrollElement = $document[0].getElementById('your_overflow_scroll_div');
    overflowScrollElement[0].scrollTop = overflowScrollElement[0].scrollHeight;

  }
]);

Só porque o agrupamento dos elementos jQuery versus elementos DOM HTML fica um pouco confuso com angular.

Também para um aplicativo de bate-papo, achei que fazer essa tarefa após o carregamento de seus bate-papos para ser útil; você também pode precisar de um tempo limite curto.

devonj
fonte
3

pequeno adendo: rola apenas, se a última linha já estiver visível. se rolado um pouco, deixa o conteúdo onde está (atenção: não foi testado com tamanhos de fonte diferentes. isso pode precisar de alguns ajustes dentro de "> = comparação"):

var objDiv = document.getElementById(id);
var doScroll=objDiv.scrollTop>=(objDiv.scrollHeight-objDiv.clientHeight);                   

// add new content to div
$('#' + id ).append("new line at end<br>"); // this is jquery!

// doScroll is true, if we the bottom line is already visible
if( doScroll) objDiv.scrollTop = objDiv.scrollHeight;
Bruno Jennrich
fonte
3

Apenas como um trecho de bônus. Estou usando o angular e estava tentando rolar um segmento de mensagem para baixo quando um usuário selecionou conversas diferentes com os usuários. Para garantir que a rolagem funcione após os novos dados terem sido carregados na div com o ng-repeat para mensagens, basta agrupar o snippet da rolagem em um tempo limite.

$timeout(function(){
    var messageThread = document.getElementById('message-thread-div-id');
    messageThread.scrollTop = messageThread.scrollHeight;
},0)

Isso garantirá que o evento de rolagem seja acionado após a inserção dos dados no DOM.

mylescc
fonte
Eu suspeito que $ scope. $ Apply (retorno de chamada) funcionaria tão bem quanto isso força uma síntese e reavaliação da exibição.
SStanley
Obrigado! Eu estava realmente me perguntando por que não consegui fazê-lo funcionar e o $ timeout foi o problema.
Wayferer 03/07/19
@Wayferer samesetTimeout(function() { ... }, n)
KingRider
3

Você também pode, usando o jQuery, anexar uma animação ao html,bodydocumento via:

$("html,body").animate({scrollTop:$("#div-id")[0].offsetTop}, 1000);

o que resultará em uma rolagem suave até o topo da div com o ID "div-id".

John Dunne
fonte
3

Script Java:

document.getElementById('messages').scrollIntoView(false);

Rola para a última linha do conteúdo presente.

Barath Sankar
fonte
2

Isso permitirá que você role a tela para baixo em relação à altura do documento

$('html, body').animate({scrollTop:$(document).height()}, 1000);
Navaneeth
fonte
1

Um método muito simples para isso é definir scroll toa altura da div.

var myDiv = document.getElementById("myDiv");
window.scrollTo(0, myDiv.innerHeight);
aravk33
fonte
1

Role até o último elemento dentro da div:

myDiv.scrollTop = myDiv.lastChild.offsetTop
mjaque
fonte
1

No meu aplicativo Angular 6, fiz o seguinte:

postMessage() {
  // post functions here
  let history = document.getElementById('history')
  let interval    
  interval = setInterval(function() {
    history.scrollTop = history.scrollHeight
    clearInterval(interval)
  }, 1)
}

A função clearInterval (intervalo) interrompe o temporizador para permitir a rolagem manual superior / inferior.

moreirapontocom
fonte
1

Meu cenário: eu tinha uma lista de strings, na qual eu tinha que anexar um string dado por um usuário e rolar para o final da lista automaticamente. Eu tinha uma altura fixa da exibição da lista, após a qual ela deveria transbordar.

Tentei a resposta de Jeremy Ruten, funcionou, mas estava rolando para o (n-1) th elemento. Se alguém estiver enfrentando esse tipo de problema, você pode usar a setTimeOut()solução alternativa do método. Você precisa modificar o código abaixo:

setTimeout(() => {
    var objDiv = document.getElementById('div_id');
    objDiv.scrollTop = objDiv.scrollHeight
}, 0)

Aqui está o link StcakBlitz que criei que mostra o problema e sua solução: https://stackblitz.com/edit/angular-ivy-x9esw8

ngShravil.py
fonte
-1

Sei que essa é uma pergunta antiga, mas nenhuma dessas soluções funcionou para mim. Acabei usando offset (). Top para obter os resultados desejados. Aqui está o que eu usei para rolar a tela suavemente até a última mensagem no meu aplicativo de chat:

$("#html, body").stop().animate({
     scrollTop: $("#last-message").offset().top
}, 2000);

Espero que isto ajude alguém.

BrianLegg
fonte
-1

Às vezes, a mais simples é a melhor solução: eu não sei se isso vai ajudar, isso me ajudou a rolar para onde sempre quis. Quanto maior o "y =", mais baixo ele rola e, claro, "0" significa superior, então, por exemplo, "1000" pode ser inferior ou "2000" ou "3000" e assim por diante, dependendo de quanto tempo o seu página é. Isso geralmente funciona em um botão com onclick ou onmouseover.

window.scrollTo(x=0,y=150);
SeekLoad
fonte
-1

Defina a distância da parte superior do elemento rolável para a altura total do elemento.

const element = this.shadowRoot.getElementById('my-scrollable-div')
element.scrollTop = element.scrollHeight
user2341537
fonte
Não adicione a mesma solução se ela já existir.
Ason
sim, não faça isso se a solução já existir
Oswaldo
-1

Você pode usar o método HTML DOM scrollIntoView da seguinte maneira:

var element = document.getElementById("scroll");
element.scrollIntoView();
Anatol
fonte
-2

usar :

var element= $('element');
var maxScrollTop = element[0].scrollHeight - element.outerHeight();
element.scrollTop(maxScrollTop);

ou verifique a rolagem para baixo:

    var element = $(element);
    var maxScrollTop = element[0].scrollHeight - element.outerHeight();
    element.on('scroll', function() {
        if ( element.scrollTop() >= maxScrollTop ) {
            alert('scroll to bottom');
        }
    });
Mahdi Bagheri
fonte
altere scrollTopMax para var maxScrollTop = elemento [0] .scrollHeight - element.outerHeight ();
Mahdi Bagheri
-2

Se isso estiver sendo feito para rolar para a parte inferior da janela de bate-papo, faça o seguinte

A ideia de rolar para uma div em particular no chat era a seguinte

1) Cada divisão de bate-papo composta por Pessoa, hora e mensagem é executada em um loop for com a classe chatContentbox

2) querySelectorAll localiza todas essas matrizes. Pode haver 400 nós (400 chats)

3) vá para o último

4) scrollIntoView ()

let lastChatBox = document.querySelectorAll('.chatContentBox'); 
lastChatBox = lastChatBox[lastChatBox.length-1]; 
lastChatBox.scrollIntoView(); 
veritas
fonte
Já são fornecidas várias respostas, usando scrollIntoView, portanto, não é necessário adicionar mais uma.
Ason