ブラウザーのオートコンプリートを自サイト内でデフォルトで無効化したい

普通に <input />
と書いただけでは要素にフォーカスを合わせた時にブラウザー独自のオートコンプリート(自動補完)の候補が表示される[1]。
既定では、ウェブサイト上の <input> 欄を通じてユーザーが送信した情報はブラウザーによって記憶されます。これよってブラウザーは、自動補完 (入力を受けた入力欄の補完候補をユーザーに提示する機能) や、オートフィル (読み込まれた入力欄をあらかじめブラウザーが補完する機能) を実現しています。
https://developer.mozilla.org/ja/docs/Web/Security/Securing_your_site/Turning_off_form_autocompletion
自分のブラウザー環境では表示されたことがないので関心が無かったが、社内でフィードバックを受けて気がついた。
-
FireFoxではフォーカスを合わせた後に更にもう一度要素をクリックする必要がある ↩︎

Chrome では 「設定→自動入力→住所やその他の情報→住所の保存と入力( chrome://settings/addresses
)」が ON になっているとオートコンプリートが表示されるようになる。
「住所の」となっているが、 <input type="text" />
など住所以外の補完にも影響しているみたい。
なぜ自分の環境ではオートコンプリートが表示されなかったかというと、1Passwordの拡張機能が無効化していたらしい。(やはり動作確認はクリーンなブラウザーで行った方が良いな…)

個別に無効化するには autocomplete
属性を off にすれば良い。
autocomplete 属性は input
textarea
select
要素に指定することができるようなので完全に無効化したい場合はそれら全てに付けた方が良い。
入力値としてテキストまたは数値を取る <input> 要素、 <textarea> 要素、 <select> 要素、 <form> 要素で利用できます。
https://developer.mozilla.org/ja/docs/Web/HTML/Attributes/autocomplete
form
要素にも指定することができて、この場合はその子孫の input
textarea
select
に一括で反映できる。
<input>, <select>, <textarea> 要素に autocomplete 属性がない場合、ブラウザーはその要素のフォームオーナー、つまりその要素を子孫に持つ <form> 要素、または <form> 要素で id がその要素の form 属性で指定されているものの autocomplete 属性の値を使用します。
https://developer.mozilla.org/ja/docs/Web/HTML/Attributes/autocomplete

今開発しているサービスでは下記の理由からサービス内のほとんどの入力欄でオートコンプリートが不要である。
- 過去の履歴から同じ内容を入力したいような input がほとんどない
- あったとしてもブラウザーによって見た目も挙動も異なるオートコンプリートには頼りたくない
- サイトのデザインに合わせて自前で実装したオートコンプリートを表示するようにしたい
そのためサービス内の全ての input でオートコンプリートを無効化し、必要な要素にだけ autocomplete
属性を明示的に指定することで有効化したい。

Atomic Design の atoms に相当するようなベースコンポーネントがある場合は、そこに autocomplete="off"
をデフォルトとして設定しておけば解決するような問題だが、今のプロダクトは Chakra UI を使用しているため、ベースコンポーネントの改変は難しい。
form
要素に autocomplete="off"
を設定することである程度一括して反映可能だが、下記の理由からやめた。

自分以外の開発者が実装する時にも autocomplete="off"
について一切考慮しなくて良いように、次のアプローチを取ることにした。
-
querySelectorAll
でinput
select
textarea
要素を探索する - 見つかった要素に
autocomplete
属性が指定されていない場合はデフォルト値としてautocomplete="off"
を設定する - これだけでは CSR で動的に追加された要素には対応できない場合がある。そのため
MutationObserver
を用いて子孫要素に更新があったら探索と設定を再度実行する
これらの処理を行うコンポーネントまたは hooks を作り、サービスのエントリーポイント [1]から呼び出す。
-
Next.jsなら
_app.tsx
、その他ならApp.tsx
など ↩︎

MutationObserver の発火頻度や querySelectorAll のパフォーマンス影響を危惧していたが、今のページ規模だと全く問題なかった。
時間がある時に動作デモを作る

この注意書きを見るにオートコンプリートは form で囲まれた要素にしか現れなさそう。
メモ: 自動補完を提供するために、ユーザーエージェントは <input>/<select>/<textarea> 要素に次のことを要求することがあります。
name や id 属性を持つこと
<form> 要素の子孫であること
フォームが submit ボタンを持つこと
https://developer.mozilla.org/ja/docs/Web/HTML/Attributes/autocomplete
ブラウザーの挙動によると思うので主要ブラウザーで確認した上で、全ての form 要素に autocomplete="off"
を付けておけばサービス内からブラウザーの autocomplete は撲滅できそう。
サービス内の form は既に10個を超えているからやはり先ほど書いた自動適用アプローチは使いたいかも。