If you have any questions or feedback, pleasefill out this form
This post is translated by ChatGPT and originally written in Mandarin, so there may be some inaccuracies or mistakes.
Introduction
This article is a compilation of methods using JavaScript after reading Implementing a pin-to-bottom scrolling element with only CSS.
Nowadays, it's increasingly common for web pages to adjust the scroll position to the bottom whenever new content is added. This is seen in comment sections like Twitch’s:
or YouTube’s comment section:
In Chinese, there doesn't seem to be a specific term for this behavior, so we'll refer to it as "pin to bottom" for now.
[JavaScript] How to Implement?
function append(comment) {
const comments = document.querySelector(".comments")
comments.appendChild(comment)
comments.scrollTop = comments.scrollHeight
}
First, set the container to a fixed height and add overflow-y: auto
. This way, when the content exceeds the height of the container, it will become scrollable.
Each time a new element is added, we simply call comments.scrollTop = comments.scrollHeight
, ensuring that scrollTop
always equals the height of scrollHeight
.
Issues to Consider
This implementation is straightforward, but it does present a problem. For example, if a user wants to scroll back to see previous content, any new comments will still force the scroll to the bottom.
To address this, we can check the current scrollTop
of the container. If there is a significant difference from scrollHeight
, we won't adjust the user's scroll position automatically.
if (
comments.offsetHeight < comments.scrollHeight &&
comments.scrollTop + comments.offsetHeight + 150 > comments.scrollHeight
) {
comments.scrollTop = comments.scrollHeight - comments.offsetHeight
}
Here, offsetHeight
represents the height of the container (CSS height), while scrollHeight
represents the total height of the container's scrollable content, and scrollTop
indicates the current scroll position.
- If it hasn't exceeded
offsetHeight
, there's no need to define any downward scrolling behavior. - If the user scrolls more than
150px
, we won't automatically scroll for them.
Additionally, if we don't assist the user with scrolling, it's common to add a button or indicator so they can jump back to the latest comments.
Furthermore, if the comments list is lengthy, there might be performance issues. There are several ways to handle this:
- Retain only the latest 500 comments (the number can be adjusted based on actual needs).
- Use a technique like windowing for optimization (though I'm unsure if it applies in cases with variable heights).
overflow-anchor
Today, I want to introduce how to achieve a similar effect using overflow-anchor. I learned about this property from the article Implementing a pin-to-bottom scrolling element with only CSS, where the author utilizes overflow-anchor
to achieve the aforementioned effect.
This property is defined in the CSS Scroll Anchoring Module. To efficiently allow users to consume content, this draft outlines how overflow-anchor
works, automatically detecting content that requires anchoring during resize or scroll actions.
You can find the detailed algorithm definitions here.
- When scrolling content S, it selects one anchor node among its child elements where the property is not
none
. - If N is within scrolling content S but cannot be seen (the original text refers to excluded subtree and fully clipped; simply put, it means not visible within the scrolling box), no action is taken.
- If N is visible within scrolling content S, it is selected as the anchor.
- If N is partially visible within scrolling content S, the algorithm continues on its child elements to find the anchor.
The draft outlines many other behaviors; if you're interested, feel free to explore it, but a basic understanding of its capabilities will suffice.
First, we add an anchor within the container:
<ul class="comments">
<li class="anchor"></li>
</ul>
Here, the anchor
needs to have the CSS property overflow-anchor: auto
to ensure the browser treats it as an anchor point.
.comments {
& > .comment {
overflow-anchor: none; // Do not treat as an anchor
}
.anchor {
overflow-anchor: auto; // Treat as an anchor
}
}
Then, modify the comment insertion to use insertBefore
to ensure the new comments are added before the anchor.
Testing Results
On the left is the standard method, while on the right is the implementation using overflow-anchor
. However, I noticed that the anchor behavior seems to require a slight scroll to function correctly.
Additionally, the text content is an excerpt from an article I wrote after reading "Gasoline Life" by Kotaro Isaka, which I conveniently copied and pasted segments from.
Currently, browser support includes Firefox 66 and Chrome 56, which is still not widespread. However, there may be new methods to implement similar functionalities in the future. Although the downside is that it requires an additional anchor, achieving this purely with CSS is quite an interesting approach.
If you found this article helpful, please consider buying me a coffee ☕ It'll make my ordinary day shine ✨
☕Buy me a coffee