Chrome 自动填充(Autofill)导致样式异常及解决方案

在做登录、注册等表单页面时,相信不少人都遇到过这样一个问题:

浏览器自动填充账号密码之后,Input 的样式突然变了

例如:

  • 背景颜色变成浅蓝色或黄色
  • 暗色模式下出现一块白色背景
  • 自定义文字颜色失效
  • Input 四个圆角出现白边或颜色异常

如果打开 DevTools,你会发现浏览器给 Input 添加了类似下面的内部样式:

input:-internal-autofill-selected

很多人第一反应就是直接去覆盖它。

遗憾的是,-internal- 开头的伪类属于 Chrome 浏览器内部实现,开发者无法直接修改。

真正应该处理的是:

input:-webkit-autofill

一、为什么会出现这个问题?

Chrome 为了提醒用户:

当前输入框的数据来自浏览器自动填充。

会主动修改 Input 的一些样式,例如:

  • background
  • color
  • box-shadow
  • text-fill-color

所以即使你的 Input 已经设置了:

input {
  background: #1f1f1f;
  color: #fff;
}

浏览器依旧可能显示成:

浅蓝背景
黑色文字

这也是为什么暗色主题下尤为明显。


二、不要覆盖 -internal-autofill-selected

很多教程都会告诉你:

input:-internal-autofill-selected {
  background: #fff;
}

实际上这是无效的。

原因很简单:

input:-internal-autofill-selected

属于浏览器内部伪类。

开发者只能处理:

input:-webkit-autofill

三、正确的解决方案

推荐统一覆盖:

input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
textarea:-webkit-autofill,
select:-webkit-autofill {
  -webkit-text-fill-color: var(--input-text-color);

  -webkit-box-shadow: 0 0 0 1000px var(--input-bg) inset;

  transition: background-color 9999s ease-in-out 0s;
}

这里最关键的是:

-webkit-box-shadow

Chrome 自动填充并不会真正修改 Input 的背景色,而是在内部绘制了一层背景。

利用:

-webkit-box-shadow: inset

可以把浏览器绘制的背景覆盖掉。


四、兼容亮色 / 暗色主题

如果网站支持 Theme 切换,不建议写死颜色。

推荐使用 CSS Variables。

:root {
  --input-bg: #ffffff;
  --input-text-color: #222222;
}

.dark {
  --input-bg: #1b1b1b;
  --input-text-color: #ffffff;
}

然后:

input:-webkit-autofill {
  -webkit-text-fill-color: var(--input-text-color);

  -webkit-box-shadow: 0 0 0 1000px var(--input-bg) inset;
}

这样主题切换后,Autofill 的样式也会自动同步。


五、为什么圆角四个角还是有白边?

很多时候,背景颜色已经正常了。

但是:

✔ 背景正常
❌ 四个圆角却露出白边

例如:

input {
  border-radius: 12px;
}

Chrome 自动填充之后:

◜      ◝
  ████
  ████
◟      ◞

四个角总感觉有一点没覆盖。

原因是:

-webkit-box-shadow

本质上只是画了一层 Inset Shadow

并没有真正修改 Input Background。

因此在部分 Chrome 版本中,圆角区域会出现渲染问题。


六、解决圆角异常

推荐增加:

input {
  border-radius: 12px;
  background-clip: padding-box;
}

然后:

input:-webkit-autofill {
  border-radius: inherit;
}

如果还有细微白边,可以把:

-webkit-box-shadow: 0 0 0 1000px ...

改成:

-webkit-box-shadow: 0 0 0 9999px var(--input-bg) inset;

不同 Chrome 版本表现略有区别。


七、推荐最终写法

下面这份代码基本可以直接放进项目中。

input {
  border-radius: 12px;
  background-clip: padding-box;
}

input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
textarea:-webkit-autofill,
select:-webkit-autofill {
  -webkit-text-fill-color: var(--input-text-color);

  -webkit-box-shadow: 0 0 0 9999px var(--input-bg) inset;

  border-radius: inherit;

  transition: background-color 9999s ease-in-out 0s;
}

主题变量:

:root {
  --input-bg: #ffffff;
  --input-text-color: #222222;
}

.dark {
  --input-bg: #1b1b1b;
  --input-text-color: #ffffff;
}

总结

Chrome 自动填充并不是普通的 CSS 样式,而是浏览器主动对 Input 做的一层特殊渲染。

因此直接修改:

background

通常并不能解决问题。

推荐的处理方式可以归纳为下面几点:

  • 不要尝试覆盖 -internal-autofill-selected
  • 使用 input:-webkit-autofill 处理自动填充样式
  • 利用 -webkit-box-shadow 覆盖浏览器默认背景
  • 使用 CSS Variables 兼容亮色 / 暗色主题
  • 配合 background-clipborder-radius 修复圆角异常

这样既能保留浏览器自动填充功能,又能保证整个网站在不同主题下保持一致的视觉效果。