🤯

【Chrome】textareaの改行時にカーソル位置がガタっとずれる問題の対処法

2021/02/20に公開

めちゃくちゃ苦しんだ結果、CSSを1行書き足すだけで解決しました。

結論
textarea { overflow-anchor: none; }

Enterキーを押すとtextareaのスクロール位置がずれる問題

ふとZennのスクラップのエディターで、Enterキーを押すと、カーソルのあたっている部分のスクロール位置がガタっとずれる問題が発生することに気づきました。

Enterキーを押したタイミングでカーソルの位置がviewportの先頭もしくは末尾にジャンプするようなイメージです。

もう少し調べてみると、Chromeでは問題が発生するものの、FirefoxやSafariでは問題が再現できませんでした。

とりあえずautosize textareaを疑う

スクラップのエディターではtextareaの高さがテキストの長さに応じて変わるreact-textarea-autosizeを使っています。最初はこのパッケージを疑ったのですが、HTMLの<textarea>タグに書き換えても問題は解消しませんでした

Reactのcursor jumpを疑う

続いてReactの下記のissueに関係しているのではないかと疑いはじめました。

Cursor jumps to end of controlled input #955

発生している問題と近いような気がしたのですが、issueに書かれているworkaroundを色々と試しても解消しませんでした

overflow-anchor: noneで解決

お手上げ状態になっていたところ、ふと「Chromeだけで起きるスクロール位置の問題……? アレじゃね?」とこちらの記事が思い浮かびました。

https://zenn.dev/nontan/articles/0cd8ea48bdf05faf1c26

数ヶ月前に、Chromeのバージョン84以降で「もっと読み込む」ボタンを押した後のスクロール位置がおかしくなる問題にぶつかっていたところ、この記事に助けられたのでした。

もしかしすると…とCSSでtextareaに対してoverflow-anchor: none;を指定したところ、ピタッと問題がおさまりました。

Image from Gyazo

のんたんさん、ありがとうございます。

overflow-anchorとは?

Chromeのバージョン84以降で「もっと見る」の挙動が変な件で分かりやすく解説されていますが、ここでも軽く説明しておきます。

ブラウザはスクロールアンカリングという仕組みで、コンテンツの読み込みにより内容が移動してしまうのを防いでくれています。つまり、今見ている部分が表示され続けるように表示位置を調整してくれるわけです。

Chromeのスクロールアンカリングはほとんどのケースでうまく機能してくれるのですが、Chrome84〜はフォーカスされている要素を優先してアンカーとして選択するようになりました。今回の問題は、Enterで改行されたときにフォーカスされたtextareaに留まり続けようと位置調整が行われた結果、ガタツキが生じてしまっていたようです。

CSSでoverflow-anchor: noneが指定された要素はアンカーの対象外になります。これによりtextareaへの位置調整が行われなくなり、問題が解決したのだと思われます。


この件について、英語・日本語どちらでググってもoverflow-anchorに触れたページは見つけられず、解決までにかなり時間がかかってしまいました。同じ問題にぶち当たった方の参考になれば嬉しいです。

Discussion