パスワードマネージャーによる自動補完でフォームのデザインが壊れる問題をCSSだけで解決する
パスワードマネージャーなどでオートコンプリート(自動補完)されたとき、
<input/> 要素の背景色や入力された文字の色が、
自分の意図しない見た目になっていたことはありませんか?
例えば、
- 背景が突然黄色や青っぽい色になる
-
background-colorを指定しているのに無視される - 文字色だけが変わり、ダークモードで読めなくなる

想定していたデザイン

オートコンプリート時
これらはCSSの指定ミスではなく、Chromeを始めとするブラウザではオートコンプリート時に、ブラウザ側が独自のスタイルを強制的に適用する仕様によるものです
メモ:
多くのブラウザーのユーザーエージェントスタイルシートでは、:-webkit-autofillスタイル定義に!importantを使用しており、JavaScript によるハックで解決しない限り、ウェブページから上書きすることができません。例えば、 Chrome では内部スタイルシートで次のようになっています。
:autofill を使った対処法
WebKit 系ブラウザでは、オートコンプリートされた<input/>要素は、:autofill擬似クラスで判別できます。
以下をコピペして、各自のデザインに合わせて使ってください
input:autofill,
input:autofill:hover,
input:autofill:focus,
input:autofill:active {
transition: background-color 5000s ease-in-out 0s;
-webkit-text-fill-color: #000 !important;
caret-color: #000;
background-color: transparent !important;
}
@media (prefers-color-scheme: light) {
input:autofill,
input:autofill:hover,
input:autofill:focus,
input:autofill:active {
-webkit-text-fill-color: #000 !important;
caret-color: #000;
}
}

オートコンプリートしても、上のように独自のデザインを維持することが出来ます
:autofill を列挙している理由
autofill状態の<input/>要素は、:hover/:focus/:active などの状態ごとに異なるスタイルが適用される場合があります。
そのため、input:autofill だけでは不十分で、フォーカス時などに一瞬だけ背景色が表示される といった挙動が発生します。
これを防ぐため、本記事では以下のようにすべての状態を明示的に指定しています。
transition: background-color 5000s の意図
autofill時に適用される背景色は、background-colorを直接上書きしようとしても無視されます。
transition: background-color 5000s ease-in-out 0s;
そこで、極端に長いtransitionを指定します。
これは背景色を変更しているのではなく、背景色の変化を事実上発生しない状態にしているという点が重要です。
なので、数秒〜数十秒程度では効果がなく、ユーザーが操作している間に変化しない長さを指定する必要があります。
-webkit-text-fill-color を使う理由
autofill時、文字色はcolorではなく、-webkit-text-fill-colorによって制御されます。
-webkit-text-fill-color: #000 !important;
この指定を行わないと、
-
colorを指定しているのに文字色が変わらない - ダークモードで文字が読めなくなる
といった問題が発生します。
また、ブラウザ側の指定が非常に強いため、!important は必要になります。
caret-color を明示している理由
これを指定しない場合、
- 文字は黒
- キャレットだけ白(またはその逆)
といった不自然な状態になることがあります。
Discussion