web-dev-qa-db-ja.com

ユーザーが上にスクロールしない限り、オーバーフローdivを下にスクロールしたままにします

私はたった300ピクセルの大きさのdivを持っていて、ページがコンテンツの一番下までスクロールするときにそれを望みます。このdivにはコンテンツが動的に追加されているので、スクロールし続ける必要があります。ユーザーが上にスクロールすることにした場合、ユーザーが再び下にスクロールするまで下にジャンプしないようにします。

ユーザーが上にスクロールして、ユーザーが下にスクロールして戻ってきても、新しい動的コンテンツが追加されても下に移動しないようにする必要があります。どうやってこれを作り出すのですか。

160

これはあなたを助けるかもしれません:

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

[編集]、コメントに一致するように...

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

コンテンツが追加されるたびに、関数updateScroll()を呼び出すか、タイマーを設定します。

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

ユーザーが移動しなかった場合にのみ更新したい場合

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

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

私はこれを実装したばかりで、おそらくあなたは私のアプローチを使うことができます。

次のようなHTMLがあるとします。

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

それからそれが一番下までスクロールしたかどうかをチェックすることができます:

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

scrollHeight はオーバーフローによる見えない部分も含めて要素の高さを返します。 clientHeight はCSSの高さを与えたり、言い換えれば要素の実際の高さを与えます。両方のメソッドともmarginなしで高さを返すので、それについて心配する必要はありません。 scrollTop 縦スクロールの位置を指定します。 0は上、maxは要素のscrollHeightから要素の高さそのものを引いたものです。スクロールバーを使うとき、スクロールバーを一番下まで動かすのは難しいかもしれません(私にとってはChromeでした)。だから私は1pxの不正確さを投げました。そのため、スクロールバーが下から1pxであってもisScrolledToBottomは真になります。あなたはこれをあなたにとって正しいと感じるものなら何にでも設定することができます。

それからそれは単に要素のscrollTopを下に設定することの問題です。

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

私はあなたが概念を示すために手間をかけました: http://jsfiddle.net/dotnetCarpenter/KpM5j/

編集:isScrolledToBottomtrueである場合を明確にするコードスニペットを追加しました。

スクロールバーを一番下に貼り付けます

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>
137
dotnetCarpenter

CSSだけでこれを動かすことができました。

トリックはdisplay: flex;flex-direction: column-reverse;を使うことです

ブラウザは下部を上部と同様に扱います。ターゲットとしているブラウザがflex-boxをサポートしていると仮定すると、唯一の注意点はマークアップの順序を逆にする必要があることです。

これが実用的な例です。 https://codepen.io/jimbol/pen/YVJzBg

116
Jim Hall
$('#yourDiv').scrollTop($('#yourDiv')[0].scrollHeight);

ライブデモ: http://jsfiddle.net/KGfG2/

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

Or animated:

$("#div1").animate({ scrollTop: $('#div1')[0].scrollHeight}, 1000);
13
Sasidharan
$('#yourDivID').animate({ scrollTop: $(document).height() }, "slow");
return false;

これは$(document).height()プロパティを使って#yourDivIDの高さからScrollTop Positionを計算するので、動的コンテンツがdivに追加されてもスクローラは常に一番下の位置になります。お役に立てれば。しかし、スクロールしてスクローラからマウスポインタを離しても自動的に一番下の位置に来ても、小さなバグがあります。誰かがそれを修正することができればそれもいいでしょう。

3
Krishnadas PC
//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;

これがdotnetCarpenterの答えに基づいた私のバージョンです。私のアプローチは純粋なjQueryであり、私は物事をもう少し明確にするために変数に名前を付けました。

IEとクロムで動作します。

2
KingOfDaNorth

Jim Hallの答えは、上にスクロールしても実際には一番下までスクロールしないが、純粋なCSSでもあるため、好ましい。

しかし残念ながら、これは安定した解決策ではありません。クロムでは(おそらく上記のdotnetCarpenterで説明されている1-px-issueのため)、scrollTopはユーザー操作なしで(要素追加時に)不正確に1ピクセル動作します。 scrollTop = scrollHeight - clientHeightを設定することはできますが、それは別の要素が追加されたときにdivを正しい位置に保ちます。別名 "下部に留まる"機能はもう機能しません。

つまり、要するに、少量のJavascript(ため息)を追加することでこれが解決され、すべての要件が満たされます。

https://codepen.io/anon/pen/pdrLEZ this(Cooによる例)のようなもので、リストに要素を追加した後も、次のようになります。

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

29は1行の高さです。

そのため、ユーザーが半行上にスクロールすると(それが可能な場合でも)、Javascriptはそれを無視して一番下までスクロールします。しかし、これは無視できないと思います。そして、Chrome 1 pxの問題を解決します。

2
Blauhirn
.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 snippet。 (PS:Run code snippetが機能しない場合は、これを試してください。 https://jsfiddle.net/Yeshen/xm2yLksu/3/

  2. それがどのように働きますか:

デフォルトのオーバーフローは上から下へのスクロールです。

transform: rotate(180deg)は動的ブロックを下から上へスクロールまたはロードすることができます。

  1. 元のアイデア:

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

1
yisheng wu

Ryan Huntによるブログ投稿 に基づいたソリューションです。 CSSプロパティoverflow-anchorに依存します。CSSプロパティは、スクロールされたコンテンツの下部にある要素にスクロール位置を固定します。

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>

overflow-anchor は現在SafariまたはEdgeでは機能しないため、このソリューションは現在すべてのブラウザーで機能しないことに注意してください。

0
mfluehr

これが私がどのようにアプローチしたかです。 divの高さは650ピクセルです。スクロールの高さが下から150px以内であれば、自動スクロールすることにしました。それ以外の場合は、ユーザーに任せます。

if (container_block.scrollHeight - container_block.scrollTop < 800) {
                    container_block.scrollTo(0, container_block.scrollHeight);
}
0
mseeba