Mantieni il div di overflow fatto scorrere verso il basso a meno che l'utente non scorri verso l'alto


223

Ho un div che è grande solo 300 pixel e lo voglio quando il caricamento della pagina scorre fino alla fine del contenuto. Questo div ha un contenuto aggiunto dinamicamente ad esso e deve rimanere scorrere fino in fondo. Ora se l'utente decide di scorrere verso l'alto, non voglio che torni indietro fino a quando l'utente scorre di nuovo completamente verso il basso

È possibile avere un div che rimarrà scorrere verso il basso a meno che l'utente non scorra verso l'alto e quando l'utente scorre di nuovo verso il basso, deve mantenersi in fondo anche quando viene aggiunto un nuovo contenuto dinamico. Come potrei andare a creare questo.


1
usa la posizione css in alto, tienilo in fondo {position : relative; bottom:0;}. Rimuovere la proprietà CSS una volta che l'utente ha lo scorrimento.
TCHdvlp,

dal momento che non hai accettato una risposta, voglio chiederti: ha funzionato per te?
Mr. Manhattan,

4
Sembra una chatbox che vuoi realizzare
Thielicious il

1
Per le novità di questa domanda, dovresti provare css snap nel 2020 .
Wener

Risposte:


136

Questo potrebbe aiutarti:

var element = document.getElementById("yourDivID");
element.scrollTop = element.scrollHeight;

[EDIT], per abbinare il commento ...

function updateScroll(){
    var element = document.getElementById("yourDivID");
    element.scrollTop = element.scrollHeight;
}

ogni volta che viene aggiunto del contenuto, chiamare la funzione updateScroll () o impostare un timer:

//once a second
setInterval(updateScroll,1000);

se si desidera aggiornare SOLO se l'utente non si è spostato:

var scrolled = false;
function updateScroll(){
    if(!scrolled){
        var element = document.getElementById("yourDivID");
        element.scrollTop = element.scrollHeight;
    }
}

$("#yourDivID").on('scroll', function(){
    scrolled=true;
});

3
Questo lo fa scorrere fino in fondo al caricamento della pagina, ma ne ho bisogno per rimanere in fondo quando viene aggiunto contenuto dinamico a meno che l'utente non abbia fatto scorrere verso l'alto.
Robert E. McIntosh,

12
Per quanto ne so, questo non riattiva lo scorrimento dinamico quando l'utente torna indietro ...
TvE

@TvE non è possibile aggiungere quel supporto?
Barkermn01,

6
Pessima soluzione. Non c'è motivo di aggiungere un setIntervalper questo lieve problema.
etancrista

6
@ethancrist tuttavia, non offri alternative ... scrollate di spalle.
Jarett Lloyd,

180

Sono stato in grado di farlo funzionare solo con CSS.

Il trucco è usare display: flex;eflex-direction: column-reverse;

Il browser tratta la parte inferiore come se fosse la parte superiore. Supponendo che i browser a cui ti rivolgi siano il supporto flex-box, l'unica avvertenza è che il markup deve essere in ordine inverso.

Ecco un esempio funzionante. https://codepen.io/jimbol/pen/YVJzBg


42
È possibile aggirare la necessità di invertire il contenuto aggiungendo un wrapper aggiuntivo e applicandolo overflow:auto; display:flex; flex-direction:column-reverse;al wrapper esterno anziché al wrapper interno.
Nathan Arthur,

6
probabilmente la soluzione migliore perché non ha bisogno di JavaScript.
Amit Kumar Khare,

3
@NathanArthur u da real mvp
php_nub_qq

13
@NathanArthur In effetti, se aggiungi un div sotto container per annullare tutto: codepen.io/anon/pen/pdrLEZ
Coo

6
Sfortunatamente questa soluzione non sembra funzionare in Firefox :(
Stuart

166

Ho appena implementato questo e forse puoi usare il mio approccio.

Supponiamo di avere il seguente HTML:

<div id="out" style="overflow:auto"></div>

Quindi possiamo verificare se scorre verso il basso con:

var out = document.getElementById("out");
// allow 1px inaccuracy by adding 1
var isScrolledToBottom = out.scrollHeight - out.clientHeight <= out.scrollTop + 1;

scrollHeight ti dà l'altezza dell'elemento, inclusa qualsiasi area non visibile a causa di trabocco. clientHeight ti fornisce l'altezza CSS o detta in altro modo, l'altezza effettiva dell'elemento. Entrambi i metodi restituiscono l'altezza senza margin, quindi non devi preoccuparti di questo. scrollTop ti dà la posizione dello scroll verticale. 0 è superiore e massimo è scrollHeight dell'elemento meno l'altezza dell'elemento stesso. Quando si utilizza la barra di scorrimento può essere difficile (era in Chrome per me) portare la barra di scorrimento fino in fondo. così ho gettato una inesattezza 1px. CosìisScrolledToBottom sarà vero anche se la barra di scorrimento è 1px dal basso. Puoi impostarlo su ciò che ritieni giusto per te.

Quindi si tratta semplicemente di impostare lo scrollTop dell'elemento in basso.

if(isScrolledToBottom)
    out.scrollTop = out.scrollHeight - out.clientHeight;

Ho creato un violino per mostrare il concetto: http://jsfiddle.net/dotnetCarpenter/KpM5j/

EDIT: snippet di codice aggiunto per chiarire quando lo isScrolledToBottomè true.

Stick barra di scorrimento verso il basso

const out = document.getElementById("out")
let c = 0

setInterval(function() {
    // allow 1px inaccuracy by adding 1
    const isScrolledToBottom = out.scrollHeight - out.clientHeight <= out.scrollTop + 1

    const newElement = document.createElement("div")

    newElement.textContent = format(c++, 'Bottom position:', out.scrollHeight - out.clientHeight,  'Scroll position:', out.scrollTop)

    out.appendChild(newElement)

    // scroll to bottom if isScrolledToBottom is true
    if (isScrolledToBottom) {
      out.scrollTop = out.scrollHeight - out.clientHeight
    }
}, 500)

function format () {
  return Array.prototype.slice.call(arguments).join(' ')
}
#out {
    height: 100px;
}
<div id="out" style="overflow:auto"></div>
<p>To be clear: We want the scrollbar to stick to the bottom if we have scrolled all the way down. If we scroll up, then we don't want the content to move.
</p>


22
Questa è in realtà l'unica soluzione che soddisfa la domanda dichiarata. E avrebbe dovuto essere contrassegnato come la risposta corretta.
preezzzy,

1
@dotnetCarpenter: Mi sembra che sia necessario if(!isScrolledToBottom): il test mi sembra sbagliato (e non ha funzionato nel mio codice fino a quando non l'ho risolto).
luskwater,

1
@luskwater puoi fornire un violino con la tua correzione? Non capisco il problema con out.scrollHeight - out.clientHeight <= out.scrollTop + 1. Stai usando il padding nel tuo CSS?
dotnetCarpenter,

2
Questo è quello che stavo cercando. E questa è la risposta alla domanda posta dall'OP. Grazie dotnetCarperter.
Luis Menjivar,

1
Se qualcuno riceve 0 quando chiama scrollTop, suggerisco di usare document.getScrollingElementcome suggerito qui: stackoverflow.com/questions/36227559/scrolltop-always-returns-0/…
Dane Jordan

29
$('#yourDiv').scrollTop($('#yourDiv')[0].scrollHeight);

Demo live: http://jsfiddle.net/KGfG2/


4
Questo lo fa scorrere fino in fondo al caricamento della pagina, ma ne ho bisogno per rimanere in fondo quando viene aggiunto contenuto dinamico a meno che l'utente non abbia fatto scorrere verso l'alto.
Robert E. McIntosh,

Funziona perfettamente. Sto aggiornando con contenuti dinamici e lo scorrimento è sempre in fondo.
Andy Bajka,

14
$('#div1').scrollTop($('#div1')[0].scrollHeight);

Or animated:

$("#div1").animate({ scrollTop: $('#div1')[0].scrollHeight}, 1000);

1
Questo lo fa scorrere fino in fondo al caricamento della pagina, ma ne ho bisogno per rimanere in fondo quando viene aggiunto contenuto dinamico a meno che l'utente non abbia fatto scorrere verso l'alto.
Robert E. McIntosh,

Questo non funziona quando div cresce molto nel primo scatto. ad esempio in Angular-js, reagire js, caricamento template Meteor Blaze, questo non funzionerà.
Ankur Soni,

Questo ha funzionato per me. Penso che funzioni bene se il div in questione rimarrà un'altezza costante. Non l'ho provato con altezze dinamiche.
doij790,

11

Nel 2020, puoi utilizzare lo snap css , ma prima di Chrome 81 la modifica del layout non attiverà il re-snap , una chat css pura funziona su Chrome 81, inoltre puoi controllare Posso usare lo snap CSS .

Questa demo farà scattare l'ultimo elemento, se visibile, scorrere verso il basso per vedere l'effetto.

.container {
  overflow-y: scroll;
  overscroll-behavior-y: contain;
  scroll-snap-type: y mandatory;
}

.container > div > div:last-child {
  scroll-snap-align: end;
}

.container > div > div {
  background: lightgray;
  height: 3rem;
  font-size: 1.5rem;
}
.container > div > div:nth-child(2n) {
  background: gray;
}
<div class="container" style="height:6rem">
<div>
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
</div>
</div>

inserisci qui la descrizione dell'immagine


5

.cont{
height: 100px;
overflow-x: hidden;
overflow-y: auto;
transform: rotate(180deg);
direction:rtl;
text-align:left;
}
ul{
overflow: hidden;
transform: rotate(180deg);
}
<div class="cont"> 
 <ul>
   <li>0</li>
   <li>1</li>
   <li>2</li>
   <li>3</li>
   <li>4</li>
   <li>5</li>
   <li>6</li>
   <li>7</li>
   <li>8</li>
   <li>9</li>
   <li>10</li>  
 </ul>
</div>

  1. Run code snippetper vedere l'effetto. (PS: se Run code snippetnon funziona, prova questo: https://jsfiddle.net/Yeshen/xm2yLksu/3/ )

  2. Come funziona:

L'overflow predefinito è lo scorrimento dall'alto verso il basso.

transform: rotate(180deg) può farlo scorrere o caricare il blocco dinamico dal basso verso l'alto.

  1. Idea originale:

https://blog.csdn.net/yeshennet/article/details/88880252


Si prega di aggiungere ulteriori spiegazioni su come il codice risolve la domanda del PO
jro

1, ha aggiunto un'introduzione aggiuntiva. 2, per favore Run code snippet, vedi direttamente l'effetto.
yisheng wu

Il pulsante dello snippet del codice di esecuzione non viene visualizzato per me. Controlla la tua formattazione
jro

È fantastico.
Includi

2
Soluzione molto creativa. Tuttavia, inverte il normale funzionamento della rotellina del mouse. Per salire, devo scorrere "verso il basso" e viceversa.
mfluehr,

3
$('#yourDivID').animate({ scrollTop: $(document).height() }, "slow");
return false;

Questo calcolerà la posizione ScrollTop dall'altezza #yourDivIDdell'utilizzo della $(document).height()proprietà in modo che anche se i contenuti dinamici vengono aggiunti al div, lo scroller sarà sempre nella posizione inferiore. Spero che questo ti aiuti. Ma ha anche un piccolo bug anche se scorriamo verso l'alto e lasciamo il puntatore del mouse dallo scroller, verrà automaticamente nella posizione inferiore. Se qualcuno potesse correggere anche quello sarebbe bello.


2
//Make sure message list is scrolled to the bottom
var container = $('#MessageWindowContent')[0];
var containerHeight = container.clientHeight;
var contentHeight = container.scrollHeight;

container.scrollTop = contentHeight - containerHeight;

Ecco la mia versione basata sulla risposta di dotnetCarpenter. Il mio approccio è un jQuery puro e ho chiamato le variabili per rendere le cose un po 'più chiare. Quello che sta succedendo è se l'altezza del contenuto è maggiore del contenitore che facciamo scorrere verso il basso per ottenere il risultato desiderato.

Funziona in IE e Chrome ..


2

La risposta di Jim Hall è preferibile perché anche se in realtà non scorre fino in fondo quando si scorre verso l'alto, è anche puro CSS.

Sfortunatamente, tuttavia, questa non è una soluzione stabile: in Chrome (probabilmente a causa del problema di 1-px descritto da dotnetCarpenter sopra), scrollTopsi comporta in modo impreciso di 1 pixel, anche senza l'interazione dell'utente (dopo l'aggiunta dell'elemento). È possibile impostare scrollTop = scrollHeight - clientHeight, ma ciò manterrà il div in posizione quando viene aggiunto un altro elemento, ovvero la funzione "Mantieni se stesso in fondo" non funziona più.

Quindi, in breve, l'aggiunta di una piccola quantità di Javascript (sospiro) risolverà questo problema e soddisferà tutti i requisiti:

Qualcosa come https://codepen.io/anon/pen/pdrLEZ questo (esempio di Coo), e dopo aver aggiunto un elemento all'elenco, anche il seguente:

container = ...
if(container.scrollHeight - container.clientHeight - container.scrollTop <= 29) {
    container.scrollTop = container.scrollHeight - container.clientHeight;
}

dove 29 è l'altezza di una linea.

Quindi, quando l'utente scorre verso l'alto di mezza riga (se è possibile?), Javascript lo ignorerà e scorrerà verso il basso. Ma immagino che questo sia trascurabile. E, risolve il problema di Chrome 1 px.


2

Ecco una soluzione basata su un post sul blog di Ryan Hunt . Dipende dalla overflow-anchorproprietà CSS, che blocca la posizione di scorrimento su un elemento nella parte inferiore del contenuto fatto scorrere.

const messages = [
  'Expect rain today.',
  'Tomorrow will be sunny.',
  'Snow is coming next week.',
  'Hailstorms are imminent.',
];

function addMessage() {
  const $message = document.createElement('div');
  $message.className = 'message';
  $message.innerText = messages[(Math.random() * messages.length) | 0];
  $messages.insertBefore($message, $anchor);

  // Trigger the scroll pinning when the scroller overflows
  if (!overflowing) {
    overflowing = isOverflowing($scroller);
    $scroller.scrollTop = $scroller.scrollHeight;
  }
}

function isOverflowing($el) {
  return $el.scrollHeight > $el.clientHeight;
}

const $scroller = document.querySelector('.scroller');
const $messages = document.querySelector('.messages');
const $anchor = document.querySelector('.anchor');
let overflowing = false;

setInterval(addMessage, 1000);
.scroller {
  overflow: auto;
  height: 90vh;
  max-height: 11em;
  background: #555;
}

.messages > * {
  overflow-anchor: none;
}

.anchor {
  overflow-anchor: auto;
  height: 1px;
}

.message {
  margin: .3em;
  padding: .5em;
  background: #eee;
}
<section class="scroller">
  <div class="messages">
    <div class="anchor"></div>
  </div>
</section>

Nota che overflow-anchorattualmente non funziona in Safari o Edge, quindi questa soluzione non funziona attualmente in tutti i browser.


1

Puoi usare qualcosa del genere,

var element = document.getElementById("yourDivID");
window.scrollTo(0,element.offsetHeight);

Spiegalo per favore!
Szabolcs Páll,

1.scrollTo è un metodo che fa scorrere l'intera finestra fino a coordinate particolari.
Yashesh Chauhan,

0

Ecco come l'ho affrontato. La mia altezza div è 650px. Ho deciso che se l'altezza di scorrimento è entro 150 px dalla parte inferiore, quindi scorrere automaticamente. Altrimenti, lascialo per l'utente.

if (container_block.scrollHeight - container_block.scrollTop < 800) {
                    container_block.scrollTo(0, container_block.scrollHeight);
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.