ให้ div ส่วนเกินเลื่อนไปด้านล่างยกเว้นว่าผู้ใช้เลื่อนขึ้น


224

ฉันมี div ที่มีขนาดใหญ่เพียง 300 พิกเซลและฉันต้องการให้มันเมื่อหน้าโหลดเลื่อนไปที่ด้านล่างของเนื้อหา div นี้มีการเพิ่มเนื้อหาแบบไดนามิกและต้องเลื่อนลงเรื่อย ๆ ตอนนี้หากผู้ใช้ตัดสินใจเลื่อนขึ้นฉันไม่ต้องการให้กระโดดกลับไปด้านล่างจนกว่าผู้ใช้จะเลื่อนลงมาอีกครั้ง

เป็นไปได้หรือไม่ที่จะมี div ที่จะยังคงเลื่อนไปที่ด้านล่างเว้นแต่ผู้ใช้เลื่อนขึ้นและเมื่อผู้ใช้เลื่อนกลับไปที่ด้านล่างจะต้องให้ตัวเองอยู่ที่ด้านล่างแม้ว่าจะมีการเพิ่มเนื้อหาแบบไดนามิกใหม่ ฉันจะสร้างการแข่งขันนี้ได้อย่างไร


1
ใช้ CSS {position : relative; bottom:0;}ตำแหน่งบนสุดเก็บไว้ที่ด้านล่าง ลบคุณสมบัติ css เมื่อผู้ใช้เลื่อน
TCHdvlp

เนื่องจากคุณไม่ยอมรับคำตอบฉันต้องการถามว่า: มันทำงานได้ดีสำหรับคุณ?
Mr.Manhattan

4
เสียงเหมือน
กล่องแชทที่

1
ใหม่คำถามนี้ควรพยายามCSS สแน็ปใน2020
พุธที่

คำตอบ:


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
ทางออกที่ไม่ดี ไม่มีเหตุผลที่จะเพิ่ม a setIntervalสำหรับปัญหาเล็กน้อยนี้
ethancrist

6
@ethancrist อย่างไรก็ตามคุณไม่มีทางเลือกอื่น ... ยักไหล่
Jarett Lloyd

180

ฉันสามารถใช้งาน CSS นี้ได้เท่านั้น

เคล็ดลับคือการใช้display: flex;และflex-direction: column-reverse;

เบราว์เซอร์ปฏิบัติด้านล่างเหมือนด้านบน สมมติว่าเบราว์เซอร์ที่คุณกำหนดเป้าหมายเป็นฝ่ายสนับสนุนflex-boxข้อแม้เดียวคือมาร์กอัพจะต้องอยู่ในลำดับย้อนกลับ

นี่คือตัวอย่างการทำงาน https://codepen.io/jimbol/pen/YVJzBg


42
คุณสามารถหลีกเลี่ยงการย้อนกลับเนื้อหาโดยเพิ่ม wrapper พิเศษและนำoverflow:auto; display:flex; flex-direction:column-reverse;ไปใช้กับ wrapper ภายนอกแทน wrapper ด้านใน
นาธานอาเธอร์

6
อาจเป็นทางออกที่ดีที่สุดเพราะไม่ต้องการจาวาสคริปต์
Amit Kumar Khare

3
@NathanArthur u da mvp จริง
php_nub_qq

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จะเป็นจริงแม้ว่าแถบเลื่อนจะเป็น 1px จากด้านล่าง คุณสามารถตั้งค่านี้เป็นอะไรก็ได้ที่คุณรู้สึกถูกต้อง

จากนั้นเป็นเพียงเรื่องของการตั้งค่า 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>


22
นี่เป็นทางออกเดียวที่สามารถตอบคำถามได้ และควรได้รับการทำเครื่องหมายว่าเป็นคำตอบที่ถูกต้อง
preezzzy

1
@dotnetCarpenter: ดูเหมือนว่าฉันต้องการif(!isScrolledToBottom): การทดสอบดูไม่ถูกต้องสำหรับฉัน (และไม่ทำงานในรหัสของฉันจนกว่าฉันจะแก้ไข)
luskwater

1
@luskwater คุณสามารถให้ fsfiddle ด้วยการแก้ไขของคุณ? out.scrollHeight - out.clientHeight <= out.scrollTop + 1ฉันไม่เข้าใจปัญหากับ คุณใช้ padding ใน CSS หรือไม่?
dotnetCarpenter

2
นี่คือสิ่งที่ฉันกำลังมองหา และนี่คือคำตอบสำหรับคำถาม OP ที่ถาม ขอบคุณ dotnetCarperter
Luis Menjivar

1
หากใครได้รับ 0 เมื่อพวกเขาเรียก scrollTop ผมแนะนำให้ใช้document.getScrollingElementตามที่แนะนำที่นี่: stackoverflow.com/questions/36227559/scrolltop-always-returns-0/…
Dane Jordan

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

การสาธิตสด: http://jsfiddle.net/KGfG2/


4
สิ่งนี้เลื่อนไปที่ด้านล่างสุดเมื่อโหลดหน้าเว็บ แต่ฉันต้องการให้อยู่ด้านล่างเมื่อเพิ่มเนื้อหาแบบไดนามิกเว้นแต่ผู้ใช้เลื่อนขึ้น
Robert E. McIntosh

มันทำงานได้อย่างสมบูรณ์แบบ ฉันกำลังอัปเดตด้วยเนื้อหาแบบไดนามิกและการเลื่อนอยู่ด้านล่างเสมอ
Andy Bajka

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 snapได้ แต่ก่อนที่ Chrome 81 การเปลี่ยนแปลงเค้าโครงจะไม่เรียกใช้ re-snap อีกครั้งการแชท css บริสุทธิ์ ui นั้นใช้งานได้บน Chrome 81 นอกจากนี้คุณสามารถตรวจสอบฉันสามารถใช้ CSS snapได้หรือไม่

การสาธิตนี้จะจัดองค์ประกอบสุดท้ายหากมองเห็นได้เลื่อนไปที่ด้านล่างเพื่อดูผลกระทบ

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

สิ่งนี้จะคำนวณตำแหน่ง ScrollTop จากความสูงของการ#yourDivIDใช้$(document).height()คุณสมบัติเพื่อให้แม้ว่าเนื้อหาแบบไดนามิกจะถูกเพิ่มใน div ผู้ scroller จะอยู่ที่ตำแหน่งด้านล่างเสมอ หวังว่านี่จะช่วยได้ แต่มันก็มีข้อผิดพลาดเล็ก ๆ แม้ว่าเราจะเลื่อนขึ้นและออกจากตัวชี้เมาส์จาก scroller มันจะมาที่ตำแหน่งด้านล่างโดยอัตโนมัติ หากใครบางคนสามารถแก้ไขได้ก็จะดี


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 และ chrome


2

คำตอบของ Jim Hall เป็นที่นิยมมากกว่าเพราะในขณะที่มันไม่ได้เลื่อนไปที่ด้านล่างเมื่อคุณเลื่อนขึ้นมันเป็น CSS ที่บริสุทธิ์

อย่างไรก็ตามน่าเสียดายอย่างมากนี่ไม่ใช่วิธีแก้ปัญหาที่เสถียร: ใน Chrome (อาจเนื่องมาจากปัญหา 1-px ที่อธิบายโดย dotnetCarpenter ด้านบน) scrollTopมีพฤติกรรมที่ไม่ถูกต้อง 1 พิกเซลแม้ว่าจะไม่มีการโต้ตอบกับผู้ใช้ก็ตาม คุณสามารถตั้งค่าscrollTop = scrollHeight - clientHeightได้ แต่นั่นจะช่วยให้ div อยู่ในตำแหน่งเมื่อมีการเพิ่มองค์ประกอบอื่นหรือที่รู้จักกันว่าคุณสมบัติ "Keep the top" ไม่ทำงานอีกต่อไป

ดังนั้นในระยะสั้นการเพิ่ม Javascript จำนวนเล็กน้อย (ถอนหายใจ) จะแก้ไขปัญหานี้และตอบสนองความต้องการทั้งหมด:

สิ่งที่ชอบ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

นี่เป็นวิธีการแก้ปัญหาบนพื้นฐานของบล็อกโพสต์โดยไรอันฮันท์ มันขึ้นอยู่กับ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 ดังนั้นขณะนี้โซลูชันนี้ใช้ไม่ได้กับเบราว์เซอร์ทั้งหมด


1

คุณสามารถใช้สิ่งนี้

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

อธิบายได้โปรด!
Szabolcs Páll

1.scrollTo เป็นวิธีการที่เลื่อนทั้งหน้าต่างไปยังพิกัดที่เฉพาะเจาะจง 2.offsetHeight จะให้ความสูงขององค์ประกอบของคุณดังนั้นบรรทัดที่สองของโค้ดด้านบนจะเลื่อนหน้าต่างลงในขณะที่คุณกำหนดบางอย่าง
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.