Faites défiler vers le bas de div?

808

Je crée un chat en utilisant les requêtes ajax dans les rails et j'essaie de faire défiler un div vers le bas sans trop de chance.

J'emballe tout dans ce div:

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

Existe-t-il un moyen de le faire défiler vers le bas par défaut en utilisant JS?

Existe-t-il un moyen de le faire défiler vers le bas après une demande ajax?

dMix
la source

Réponses:

1326

Voici ce que j'utilise sur mon site:

var objDiv = document.getElementById("your_div");
objDiv.scrollTop = objDiv.scrollHeight;
Jeremy Ruten
la source
13
cette méthode est-elle compatible avec tous les navigateurs?
jondinham
1
@PaulDinh: Je viens de regarder cela et il y a un problème avec IE7 et inférieur en utilisant scrollHeight. Il semble y avoir un travail pour IE7 ici .
Sean
3
Pourquoi cela ne fonctionne-t-il pas après l'ajout dynamique d'éléments à l'intérieur de la div?
Vince
3
@Vince - C'est une affaire unique. Si vous modifiez le contenu, vous devrez réexécuter. La commande dit essentiellement "déplacez la barre de défilement à cette position".
DrFriedParts
8
Et en plus, si vous avez des éléments placés à l'intérieur d'un div par exemple, vous pouvez faire défiler un élément particulier en vue. (c'est-à-dire que l'élément est visible à l'intérieur du div parent) .. comme ceci: $ ("#" + instanceID) .scrollTop ($ ("#" + instanceID) [0] .scrollIntoView);
netfed
360

C'est beaucoup plus facile si vous utilisez jQuery scrollTop :

$("#mydiv").scrollTop($("#mydiv")[0].scrollHeight);
andsien
la source
273
Comment est-ce plus simple?
captainspi
78
1 ligne au lieu de 2? aucun indice, mais ce que vous pouvez faire facilement avec JQuery est d'animer l'action comme ceci: $ ("# div-id"). animate ({scrollTop: $ ("# div-id") [0] .scrollHeight}, 1000 ); j'espère que cela aide n'importe qui :)
Samuel
28
vous avez besoin de [0] pour obtenir l'élément dom de l'élément jquery pour obtenir scrollHeight
Jimmy Bosse
14
"Sans oublier que le JQ est plus difficile à lire / comprendre!" Une pure opinion. Par exemple, je trouve JQuery beaucoup plus facile à lire, à comprendre et à utiliser. Et cette solution EST meilleure si vous utilisez déjà JQuery de toute façon.
Hanna
47
Sans vous répéter:$("#mydiv").scrollTop(function() { return this.scrollHeight; });
Eric
98

Vous pouvez utiliser le code suivant:

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

Pour effectuer un défilement fluide avec JQuery:

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

Voir l' exemple sur JSFiddle

Voici pourquoi cela fonctionne:

entrez la description de l'image ici

Réf: scrollTop , scrollHeight , clientHeight

Tho
la source
92

en utilisant jQuery animate :

$('#DebugContainer').stop().animate({
  scrollTop: $('#DebugContainer')[0].scrollHeight
}, 800);
PapaViegas
la source
5
C'est ce que Sam a dit dans ce commentaire . C'est probablement plus utile dans une réponse réelle!
Quentin Pradet
6
Remarquez comment cette réponse utilise .stop () , ce qui évite les problèmes avec plusieurs animations.
kalyfe
Étonnamment, c'est la seule qui fonctionne pour moi parmi toutes les réponses précédentes. Cela peut être dû à la façon dont mes autres divs sont configurées autour de la couche qui doit continuer à défiler
Duniyadnd
Ce fut le seul qui a fonctionné pour moi (
j'ajoute des
36
var mydiv = $("#scroll");
mydiv.scrollTop(mydiv.prop("scrollHeight"));

Fonctionne à partir de jQuery 1.6

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

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

Akira Yamamoto
la source
1
Cette solution fonctionne pour les éléments avec une classe CSS unique mais sans ID CSS. La solution du premier commentaire ne fonctionne pas prête à l'emploi avec une classe CSS.
CFitz
31

Méthode plus récente qui fonctionne sur tous les navigateurs actuels :

this.scrollIntoView(false);
tnt-rox
la source
1
Pensez que cela ne fonctionne que sur Firefox: developer.mozilla.org/en/docs/Web/API/Element/…
Amrit Kahlon
3
Le support manque en effet atm, mais si cela est accepté, ce serait génial.
Kristjan Liiva
Les mises à jour? Je pense que cela devrait être accepté comme la bonne réponse. Je veux dire venir sur jQuery?
lkahtz
travail: document.querySelector (". mdl-list"). scrollIntoView (false);
Johann Medina
15

défilement fluide avec Javascript:

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

adl
la source
8

Si vous ne voulez pas vous fier scrollHeight, le code suivant vous aide:

$('#scroll').scrollTop(1000000);
Benny Neugebauer
la source
1
Aucune des solutions ci-dessus, y compris la vôtre, ne semble fonctionner sur Firefox sur Android ... des pensées s'il vous plaît?
Kaya Toast
Peu importe, j'utilisais un trop grand nombre ( 1E10). Un plus petit nombre fonctionne
andrewtweber
Ça compte toujours
Ben Taliadoros
4
Pourquoi serait-ce une mauvaise performance? Ce n'est pas comme s'il itérait sur chaque pixel. Maintenant, les mauvaises pratiques sont une autre question…
devios1
$ ('# scroll'). scrollTop (Infinity), cela devrait aussi fonctionner alors.
Madhav Poudel
5

En utilisant jQuery, scrollTop est utilisé pour définir la position verticale de la barre de défilement pour un élément donné. il y a aussi un joli plugin jquery scrollTo utilisé pour faire défiler avec animation et différentes options ( démos )

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

si vous souhaitez utiliser la méthode d'animation de jQuery pour ajouter une animation lors du défilement, vérifiez l'extrait de code suivant:

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

J'ai rencontré le même problème, mais avec une contrainte supplémentaire: je n'avais aucun contrôle sur le code qui ajoutait de nouveaux éléments au conteneur de défilement. Aucun des exemples que j'ai trouvés ici ne m'a permis de faire exactement cela. Voici la solution avec laquelle je me suis retrouvé.

Il utilise Mutation Observers( https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver ) ce qui le rend utilisable uniquement sur les navigateurs modernes (bien qu'il existe des polyfills)

Donc, fondamentalement, le code fait exactement cela:

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

J'ai fait un violon pour démontrer le concept: https://jsfiddle.net/j17r4bnk/

Benkinass
la source
comment obtenir un identifiant dynamique? comme dans <div class="abc"><div data-bind=attr : {'id': myId } ></div></div>ce code, myId est une variable. Comment puis-je accéder à cet identifiant dans le script.
Irfan Yusanif,
Je ne suis pas sûr de comprendre votre question. Dans mon exemple, "myId" est l'ID du conteneur de défilement. Voulez-vous créer plusieurs zones dans lesquelles l'utilisateur peut faire défiler?
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
la source
4

J'ai trouvé cela vraiment utile, merci.

Pour les gens Angular 1.X:

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;

  }
]);

Tout simplement parce que l'encapsulation des éléments jQuery par rapport aux éléments HTML DOM devient un peu déroutant avec angulaire.

Aussi pour une application de chat, j'ai trouvé que faire cette tâche après le chargement de vos chats était utile, vous pourriez également avoir besoin de gifler sur un court délai.

devonj
la source
3

petit addenda: défile uniquement si la dernière ligne est déjà visible. s'il défile un peu, laisse le contenu où il se trouve (attention: non testé avec différentes tailles de police. cela peut nécessiter quelques ajustements à l'intérieur de "> = comparaison"):

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
la source
3

Tout comme un extrait de bonus. J'utilise angulaire et essayais de faire défiler un fil de messages vers le bas lorsqu'un utilisateur a sélectionné différentes conversations avec les utilisateurs. Afin de vous assurer que le défilement fonctionne après que les nouvelles données ont été chargées dans le div avec la répétition ng pour les messages, enveloppez simplement l'extrait de défilement dans un délai d'attente.

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

Cela garantira que l'événement de défilement est déclenché après que les données ont été insérées dans le DOM.

mylescc
la source
Je soupçonne que $ scope. $ Apply (callback) fonctionnerait aussi bien que cela force un résumé et une réévaluation de la vue.
SStanley
Je vous remercie! Je me demandais vraiment pourquoi je ne pouvais pas le faire fonctionner et le délai d'attente $ était le problème.
Wayferer
@Wayferer samesetTimeout(function() { ... }, n)
KingRider
3

Vous pouvez également, à l'aide de jQuery, attacher une animation au html,bodydocument via:

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

ce qui se traduira par un défilement fluide vers le haut de la div avec l'ID "div-id".

John Dunne
la source
3

Script Java:

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

Fait défiler jusqu'à la dernière ligne du contenu présent.

Barath Sankar
la source
2

Cela vous permettra de faire défiler vers le bas en ce qui concerne la hauteur du document

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

Une méthode très simple consiste à définir scroll tola hauteur du div.

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

Faites défiler jusqu'au dernier élément à l'intérieur de la div:

myDiv.scrollTop = myDiv.lastChild.offsetTop
mjaque
la source
1

Sur mon application Angular 6, je viens de faire ceci:

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

La fonction clearInterval (interval) arrêtera la minuterie pour permettre un défilement manuel en haut / en bas.

moreirapontocom
la source
1

Mon scénario: j'avais une liste de chaînes, dans laquelle je devais ajouter une chaîne donnée par un utilisateur et faire défiler jusqu'à la fin de la liste automatiquement. J'avais fixé la hauteur de l'affichage de la liste, après quoi elle devait déborder.

J'ai essayé la réponse de @Jeremy Ruten, cela a fonctionné, mais il défilait jusqu'au (n-1) e élément. Si quelqu'un rencontre ce type de problème, vous pouvez utiliser la setTimeOut()méthode de contournement. Vous devez modifier le code ci-dessous:

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

Voici le lien StcakBlitz que j'ai créé qui montre le problème et sa solution: https://stackblitz.com/edit/angular-ivy-x9esw8

ngShravil.py
la source
-1

Je sais que c'est une vieille question, mais aucune de ces solutions n'a fonctionné pour moi. J'ai fini par utiliser offset (). Top pour obtenir les résultats souhaités. Voici ce que j'ai utilisé pour faire défiler doucement l'écran jusqu'au dernier message de mon application de chat:

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

J'espère que ça aidera quelqu'un d'autre.

BrianLegg
la source
-1

Parfois, la plus simple est la meilleure solution: je ne sais pas si cela va aider, cela m'a aidé à faire défiler ce que je voulais aussi. Plus le "y =" est élevé, plus il défile vers le bas et bien sûr "0" signifie en haut, donc par exemple "1000" peut être en bas, ou "2000" ou "3000" et ainsi de suite, selon la durée de votre page est. Cela fonctionne généralement dans un bouton avec onclick ou onmouseover.

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

Définissez la distance entre le haut de l'élément déroulant et la hauteur totale de l'élément.

const element = this.shadowRoot.getElementById('my-scrollable-div')
element.scrollTop = element.scrollHeight
user2341537
la source
N'ajoutez pas la même solution si elle existe déjà.
Ason
ouais ne fais pas ça si la solution existe déjà
Oswaldo
-1

Vous pouvez utiliser la méthode HTML DOM scrollIntoView comme ceci:

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

utilisation :

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

ou vérifiez défiler vers le bas:

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

Si cela est fait pour faire défiler vers le bas de la fenêtre de discussion, procédez comme suit

L'idée de faire défiler jusqu'à un div particulier dans le chat était la suivante

1) Chaque div de chat comprenant une personne, une heure et un message est exécutée dans une boucle for avec la classe chatContentbox

2) querySelectorAll trouve tous ces tableaux. Cela pourrait être 400 nœuds (400 chats)

3) allez au dernier

4) scrollIntoView ()

let lastChatBox = document.querySelectorAll('.chatContentBox'); 
lastChatBox = lastChatBox[lastChatBox.length-1]; 
lastChatBox.scrollIntoView(); 
veritas
la source
Plusieurs réponses sont déjà données, en utilisant scrollIntoView, donc pas besoin d'en ajouter encore une de plus.
Ason