사용자가 위로 스크롤하지 않으면 overflow div를 맨 아래로 스크롤 한 상태로 유지


224

300 픽셀 크기의 div가 있으며 페이지가 내용의 맨 아래로 스크롤 될 때 원합니다. 이 div에는 동적으로 콘텐츠가 추가되어 계속 스크롤되어 있어야합니다. 이제 사용자가 위로 스크롤하기로 결정한 경우 사용자가 다시 아래로 스크롤 할 때까지 맨 아래로 다시 이동하고 싶지 않습니다.

사용자가 위로 스크롤하지 않으면 사용자가 맨 아래로 스크롤하지 않으면 맨 아래로 스크롤 된 div를 가질 수 있습니까? 그리고 사용자가 맨 아래로 다시 스크롤하면 새로운 동적 내용이 추가 된 경우에도 맨 아래에 있어야합니다. 이것을 만들어내는 방법은 무엇입니까?


1
CSS 위치 상단을 사용하여 하단에 유지하십시오 {position : relative; bottom:0;}. 사용자가 스크롤하면 css 속성을 제거하십시오.
TCHdvlp

당신이 대답을 받아들이지 않았기 때문에 묻고 싶습니다.
Mr.Manhattan

4
달성하고자하는
대화 상자

1
이 질문을 처음 접하려면 2020 년에 CSS 스냅 을 시도해야합니다 .
wener

답변:


136

이것은 당신을 도울 수 있습니다 :

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

3
이것은 페이지로드시 맨 아래로 스크롤되지만 사용자가 위로 스크롤하지 않으면 동적 내용이 추가 될 때 맨 아래에 있어야합니다.
Robert E. McIntosh

12
내가 알 수있는 한 이것은 사용자가 맨 아래로 다시 스크롤 할 때 동적 스크롤을 다시 활성화하지 않는다 ...
TvE

@TvE 지원을 추가 할 수 없습니까?
Barkermn01

6
나쁜 해결책. setInterval이 가벼운 문제 를 추가 할 이유가 없습니다 .
ethancrist

6
@ethancrist 그러나, 당신은 대안을 제공하지 않습니다 ... 어깨를 으 s.
Jarett Lloyd

180

CSS로만 작동하도록 할 수있었습니다.

트릭은 사용 display: flex;하고flex-direction: column-reverse;

브라우저는 하단을 상단과 같이 취급합니다. 지원하는 브라우저를 지원한다고 가정하면 flex-box유일한주의 사항은 마크 업이 역순이어야한다는 것입니다.

다음은 실제 예입니다. https://codepen.io/jimbol/pen/YVJzBg


42
추가 래퍼를 추가 overflow:auto; display:flex; flex-direction:column-reverse;하고 내부 래퍼 대신 외부 래퍼에 적용하여 내용을 되돌려 야하는 문제를 해결할 수 있습니다 .
Nathan Arthur

6
아마도 자바 스크립트가 필요하지 않기 때문에 가장 좋은 해결책 일 것입니다.
Amit Kumar Khare

3
@NathanArthur u da real mvp
php_nub_qq 1

13
@NathanArthur 사실, 컨테이너 아래에 div를 추가하여 모든 것을 취소하려면 codepen.io/anon/pen/pdrLEZ
Coo

6
불행히도이 솔루션은 Firefox에서 작동하지 않는 것 같습니다 :(
Stuart

166

방금 이것을 구현했으며 아마도 내 접근 방식을 사용할 수 있습니다.

다음 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은 상단이고 최대는 요소의 scrollHeight에서 요소 높이를 뺀 값입니다. 스크롤 막대를 사용할 때 스크롤 막대를 맨 아래로 내리는 것이 어려울 수 있습니다 (Chrome에서는 저에게 있습니다). 그래서 나는 1px 부정확성을 던졌습니다. 그래서 isScrolledToBottom스크롤이 바닥에서 1 픽셀의 경우에도 마찬가지 일 것이다. 당신은 당신에게 맞는 느낌으로 이것을 설정할 수 있습니다.

그런 다음 단순히 요소의 scrollTop을 맨 아래로 설정하면됩니다.

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

나는 당신이 개념을 보여주기 위해 바이올린을 만들었습니다 : http://jsfiddle.net/dotnetCarpenter/KpM5j/

편집 : 때 추가 된 코드는 명확히 isScrolledToBottom이다 true.

스크롤바를 아래로 붙입니다

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
이것은 실제로 명시된 질문을 수행하는 유일한 솔루션입니다. 정답으로 표시되어 있어야합니다.
preezzzy

1
@dotnetCarpenter : 그것은 당신이 필요 것처럼 나에게 보이는 if(!isScrolledToBottom)테스트가 나에게 잘못 보인다 (과에서 일을하지 않았다 : 나는 그것을 고정 될 때까지 코드).
luskwater

1
@luskwater 당신은 당신의 수정으로 fsfiddle을 제공 할 수 있습니까? 의 문제를 이해하지 못합니다 out.scrollHeight - out.clientHeight <= out.scrollTop + 1. CSS에서 패딩을 사용하고 있습니까?
dotnetCarpenter

2
이것이 내가 찾던 것입니다. 그리고 이것은 OP가 묻는 질문에 대한 답변입니다. dotnetCarperter에게 감사합니다.
Luis Menjivar

1
사람이 공을 받고 있다면 그들은 내가 사용하는 것이 좋습니다, scrollTop를 호출 할 때 document.getScrollingElement여기 제안 : stackoverflow.com/questions/36227559/scrolltop-always-returns-0/...
덴마크 요르단

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

라이브 데모 : http://jsfiddle.net/KGfG2/


4
이것은 페이지로드시 맨 아래로 스크롤되지만 사용자가 위로 스크롤하지 않으면 동적 내용이 추가 될 때 맨 아래에 있어야합니다.
Robert E. McIntosh

이것은 완벽하게 작동합니다. 동적 콘텐츠로 업데이트 중이며 스크롤이 항상 맨 아래에 있습니다.
앤디

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

Or animated:

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

1
이것은 페이지로드시 맨 아래로 스크롤되지만 사용자가 위로 스크롤하지 않으면 동적 내용이 추가 될 때 맨 아래에 있어야합니다.
Robert E. McIntosh

첫 번째 샷에서 div가 많이 자라면 작동하지 않습니다. 예를 들어 Angular-js에서는 반응 js, Meteor Blaze 템플릿 로딩이 작동하지 않습니다.
Ankur Soni

이것은 나를 위해 일했습니다. 문제의 div가 일정한 높이를 유지하면 제대로 작동한다고 생각합니다. 동적 높이로 테스트하지 않았습니다.
doij790

11

2020 년, 당신이 사용할 수있는 CSS 스냅을 하지만, 크롬 81 레이아웃 변경하기 전에 것입니다 트리거 다시 스냅하지 하는 UI를 채팅 순수 CSS를 크롬 81에서 작동도 확인할 수 있습니다 할 수 있습니까 CSS를 사용 스냅을 .

이 데모는 보이는 경우 마지막 요소를 스냅하고 아래로 스크롤하여 효과를 봅니다.

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

여기에 이미지 설명을 입력하십시오


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 snippet효과를 볼 수 있습니다. (PS : Run code snippet작동하지 않으면 다음을 시도하십시오 : https://jsfiddle.net/Yeshen/xm2yLksu/3/ )

  2. 작동 방식 :

기본 오버플로는 위에서 아래로 스크롤됩니다.

transform: rotate(180deg) 스크롤하거나 동적 블록을 아래에서 위로 만들 수 있습니다.

  1. 독창적 인 아이디어 :

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


코드가 OP의 문제를 해결하는 방법에 대한 자세한 설명을 추가하십시오
jro

1, 추가 소개를 추가했습니다. 2, Run code snippet직접 효과를 참조하십시오.
yisheng wu

실행 코드 스 니펫 버튼이 표시되지 않습니다. 형식 확인
jro

훌륭합니다. 답변에 링크를 포함 시키십시오
jro

2
매우 창의적인 솔루션. 그러나 마우스 스크롤 휠의 정상적인 작동과 반대입니다. 올라가려면 "아래로"스크롤해야하며 그 반대도 마찬가지입니다.
mfluehr

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

이 속성 을 #yourDivID사용하여 높이에서 ScrollTop 위치를 계산하여 $(document).height()동적 내용이 div에 추가 되더라도 스크롤러가 항상 맨 아래 위치에있게됩니다. 도움이 되었기를 바랍니다. 그러나 스크롤을하여 스크롤러에서 마우스 포인터를 떼어도 자동으로 맨 아래 위치에 오더라도 작은 버그가 있습니다. 누군가가 그 문제를 해결할 수 있다면 좋을 것입니다.


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;

다음은 dotnetCarpenter의 답변을 기반으로 한 내 버전입니다. 내 접근 방식은 순수한 jQuery이며 상황을 좀 더 명확하게하기 위해 변수의 이름을 지정했습니다. 내용 높이가 컨테이너보다 크면 컨테이너가 원하는 거리를 초과하여 원하는 결과를 얻습니다.

IE와 크롬에서 작동합니다.


2

Jim Hall의 답변은 스크롤 할 때 실제로 맨 아래로 스크롤되지 않지만 순수한 CSS이기 때문에 선호됩니다.

그러나 불행히도 이것은 안정적인 솔루션이 아닙니다. 크롬에서 (위의 dotnetCarpenter가 설명한 scrollTop1 픽셀 문제로 인해) 사용자 상호 작용 (요소 추가시)이 없어도 1 픽셀만큼 부정확하게 작동합니다. 을 설정할 수는 scrollTop = scrollHeight - clientHeight있지만 다른 요소가 추가 될 때 div 위치를 유지합니다. 즉, "자체를 맨 아래에 유지"기능이 더 이상 작동하지 않습니다.

즉, 소량의 Javascript (sigh)를 추가하면이 문제가 해결되고 모든 요구 사항이 충족됩니다.

https://codepen.io/anon/pen/pdrLEZ 와 같은 것 (예 : Coo의 예) 및 요소를 목록에 추가 한 후 다음 사항도 수행하십시오.

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

여기서 29는 한 줄의 높이입니다.

따라서 사용자가 반 줄을 스크롤하면 (가능한 경우) Javascript는이를 무시하고 맨 아래로 스크롤합니다. 그러나 이것은 무시할 수 있다고 생각합니다. 그리고 Chrome 1 px를 수정합니다.


2

Ryan Hunt의 블로그 게시물을 기반으로 한 솔루션이 있습니다. overflow-anchorCSS 속성 에 따라 스크롤되는 위치를 스크롤 된 내용의 맨 아래에있는 요소에 고정시킵니다.

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이 솔루션은 현재 모든 브라우저에서 작동하지 않도록, 사파리 또는 Edge 현재 일을하지 않습니다.


1

이런 식으로 사용할 수 있습니다

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

설명해주세요!
Szabolcs Páll

1. scrollTo는 전체 창을 특정 좌표로 스크롤하는 메소드입니다.
Yashesh Chauhan

0

내가 접근 한 방법은 다음과 같습니다. 내 div 높이는 650px입니다. 스크롤 높이가 아래쪽의 150px 내에 있으면 자동 스크롤하기로 결정했습니다. 그렇지 않으면 사용자를 위해 남겨 두십시오.

if (container_block.scrollHeight - container_block.scrollTop < 800) {
                    container_block.scrollTo(0, container_block.scrollHeight);
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.