【Chrome】textareaの改行時にカーソル位置がガタっとずれる問題の対処法
めちゃくちゃ苦しんだ結果、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だけで起きるスクロール位置の問題……? アレじゃね?」とこちらの記事が思い浮かびました。
数ヶ月前に、Chromeのバージョン84以降で「もっと読み込む」ボタンを押した後のスクロール位置がおかしくなる問題にぶつかっていたところ、この記事に助けられたのでした。
もしかしすると…とCSSでtextarea
に対してoverflow-anchor: none;
を指定したところ、ピタッと問題がおさまりました。
のんたんさん、ありがとうございます。
overflow-anchor
とは?
Chromeのバージョン84以降で「もっと見る」の挙動が変な件で分かりやすく解説されていますが、ここでも軽く説明しておきます。
ブラウザはスクロールアンカリングという仕組みで、コンテンツの読み込みにより内容が移動してしまうのを防いでくれています。つまり、今見ている部分が表示され続けるように表示位置を調整してくれるわけです。
Chromeのスクロールアンカリングはほとんどのケースでうまく機能してくれるのですが、Chrome84〜はフォーカスされている要素を優先してアンカーとして選択するようになりました。今回の問題は、Enterで改行されたときにフォーカスされたtextarea
に留まり続けようと位置調整が行われた結果、ガタツキが生じてしまっていたようです。
CSSでoverflow-anchor: none
が指定された要素はアンカーの対象外になります。これによりtextarea
への位置調整が行われなくなり、問題が解決したのだと思われます。
この件について、英語・日本語どちらでググってもoverflow-anchor
に触れたページは見つけられず、解決までにかなり時間がかかってしまいました。同じ問題にぶち当たった方の参考になれば嬉しいです。
Discussion