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?

Réponses:


1326

Voici ce que j'utilise sur mon site:

var objDiv = document.getElementById("your_div");
objDiv.scrollTop = objDiv.scrollHeight;

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

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


92

en utilisant jQuery animate :

$('#DebugContainer').stop().animate({
  scrollTop: $('#DebugContainer')[0].scrollHeight
}, 800);

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


31

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

this.scrollIntoView(false);

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


8

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

$('#scroll').scrollTop(1000000);

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

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/


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

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.


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;

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.


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".


3

Script Java:

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

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


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

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

1

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

myDiv.scrollTop = myDiv.lastChild.offsetTop

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.


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


-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.


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

-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

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

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

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

Plusieurs réponses sont déjà données, en utilisant scrollIntoView, donc pas besoin d'en ajouter encore une de plus.
Ason
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.