Kalan's Blog

Kalan 頭像照片,在淡水拍攝,淺藍背景

四零二曜日電子報上線啦!訂閱訂起來

Software Engineer / Taiwanese / Life in Fukuoka
This blog supports RSS feed (all content), you can click RSS icon or setup through third-party service. If there are special styles such as code syntax in the technical article, it is still recommended to browse to the original website for the best experience.

Current Theme light

我會把一些不成文的筆記或是最近的生活雜感放在短筆記,如果有興趣的話可以來看看唷!

Please notice that currenly most of posts are translated by AI automatically and might contain lots of confusion. I'll gradually translate the post ASAP

Implementing the pin to bottom component via overflow-anchor

Introduction

This article is a summary of the approach using JavaScript, after reading Implementing a pin-to-bottom scrolling element with only CSS.

Nowadays, it is common to see web pages automatically scrolling to the bottom whenever new content is added. For example, the comment sections on platforms like Twitch and YouTube.

In Chinese, there doesn't seem to be a specific term for this behavior, so let's call it "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 allows the content to scroll when it exceeds the container's height.

Whenever a new element is added, simply call comments.scrollTop = comments.scrollHeight to ensure that the scrollTop always equals the height of scrollHeight.

Considerations

Although this implementation is straightforward, there is one issue to address. When users want to scroll back to view other content, if new comments appear, the page will still force scroll to the bottom.

To solve this, we can check the current scrollTop of the container. If there is a significant difference compared to scrollHeight, we won't automatically scroll for the user.

if (
  comments.offsetHeight < comments.scrollHeight &&
  comments.scrollTop + comments.offsetHeight + 150 > comments.scrollHeight
) {
  comments.scrollTop = comments.scrollHeight - comments.offsetHeight
}

Here, offsetHeight represents the container's height (CSS height), scrollHeight represents the total scrolled height of the container, and scrollTop represents the current scroll position.

  1. If it has not exceeded offsetHeight, there's no need to define the scrolling behavior.
  2. If the user has scrolled more than 150px, we won't automatically scroll for them.

Additionally, if we don't automatically scroll, it is common to add a button or indicator for the user to jump to the latest comment.

Another potential performance issue can arise if the comment list is very long. There are a few ways to handle this:

  1. Keep only the latest 500 comments (the specific number depends on the actual requirement).
  2. Optimize using techniques like windowing (though it may not be suitable for variable heights).

overflow-anchor

Today, I want to introduce a method to achieve a similar effect using overflow-anchor. I came across this property in the article Implementing a pin-to-bottom scrolling element with only CSS. The article explains how to achieve the desired effect using overflow-anchor.

This property is defined in the CSS Scroll Anchoring Module. To efficiently allow users to consume content, this draft defines the behavior of overflow-anchor. It automatically detects the content that needs to be anchored when resizing or scrolling occurs.

The detailed algorithm definition can be found here.

  1. When scrolling content S, select an anchor node from the child elements whose overflow-anchor property is not none.
  2. If N is inside scrolling content S and cannot be seen (excluded subtree or fully clipped, meaning it is not visible within the scrolling frame), do nothing.
  3. If N is visible inside scrolling content S, select N as the anchor node.
  4. If N is partially visible inside scrolling content S, continue the algorithm on the child elements to find the anchor node.

The draft defines many other behaviors, so feel free to explore if interested. However, understanding what it can do is sufficient.

First, we add an anchor within the container:

<ul class="comments">
  <li class="anchor"></li>
</ul>

The anchor should have the CSS property overflow-anchor: auto to make the browser recognize it as an anchor.

.comments {
  & > .comment {
    overflow-anchor: none; // Not an anchor
  }

  .anchor {
    overflow-anchor: auto; // Anchor
  }
}

Then, change the way comments are added using insertBefore to ensure they are inserted before the anchor.

Test Results

On the left is the regular approach, while on the right is the implementation using overflow-anchor. However, I noticed that scrolling the anchor is required for it to work correctly.

As an additional note, the text content used is from an article I wrote after reading "Gasoline Life" by Kotaro Isaka. I copied a few paragraphs for convenience.

Currently, browser support is limited to Firefox 66 and Chrome 56, so it is not widely adopted. However, there may be new approaches in the future for similar functionality. Although the drawback is the need to add an additional anchor, it is an interesting method achieved purely with CSS.

Prev

Safer Request Headers - Fetch Metadata Request Headers

Next

Setting Environment Variables for a Project - VIPER

If you found this article helpful, please consider buy me a drink ☕️ It'll make my ordinary day shine✨

Buy me a coffee