概要
単純にflex-col-reverse
とoverflow-y-scroll
を組み合わせるだけで実現可能。
なのだけど、shadcn/uiのScrollAreaと組み合わせて使った際にドツボにハマってしまったので備忘録。
最終的にScrollAreaは使わないことにした(書き方の問題だとは思うものの、最下部に移動させられなかった)。
結論
<div className="flex h-screen flex-1 flex-col bg-[#FFFFFF] dark:bg-[#313338]">
{/** チャンネルアクション */}
<div className="relative">チャットヘッダ部</div>
<div className="flex flex-1 flex-col-reverse overflow-y-scroll">
{chatSample.map((chat) => (
<div key={chat.id} className="mt-16 flex items-center">
<UserAvatar name={chat.name} image={chat.image} />
<div className="flex gap-2">
<span>{chat.name}</span>
<span>{chat.message}</span>
<span>{chat.time}</span>
</div>
</div>
))}
</div>
{/** チャット一覧の最下部 */}
<div id="chat-list-bottom" />
<div className="relative bottom-0">チャット入力欄</div>
</div>
失敗 <scriptタグ>
本番環境では上手くいくのかもしれないが、スクロールさせたい位置にscriptタグを埋め込んで要素の高さを取ってくる手法。 Stackoverflowのコメントにあるように高さが0で取れるため、動作するか分からず。

<script>
var element = document.currentScript.previousElementSibling;
element.scrollTop = element.scrollHeight - element.clientHeight;
</script>
This version actually works in production. It doesn’t work in development because Next.js use’s Webpack’s style-loader in development which means styles don’t load until the JavaScript code has loaded and the JavaScript code is loaded at the end of the document .
So in production element.clientHeight will be correct (since the CSS was loaded in the ) but in development element.clientHeight will be 0 (since the CSS will be loaded at the end of ).
このバージョンは実際に本番環境で動作します。開発環境では動作しません。なぜなら、Next.jsは開発環境でWebpackのstyle-loaderを使用しており、これによりスタイルがJavaScriptコードが読み込まれるまでロードされません。JavaScriptコードはドキュメントの の最後に読み込まれます。
そのため、本番環境では element.clientHeight は正しい値になります(CSSが 内で読み込まれるため)、しかし開発環境では element.clientHeight は0になります(CSSが の最後に読み込まれるため)。

失敗 useRef
useRefでスクロール位置を計算する方法を取るも、こちらも同じく計算が上手くいかなかった(同じ理由だろうか)