学完这篇,你能搞清楚浏览器到底凭什么决定「这个输入框该填什么」,并用几行属性和 CSS 把自动填充的行为按你的意愿掰过来——该填的填准,不该弹的别弹。
第一步:先明白浏览器不看你的 autocomplete
很多人以为 autocomplete="off" 是总开关,其实浏览器把它当"建议"。Chrome 判断一个框填什么,主要看四样东西:type、name/id、<label> 文本、placeholder。只要表单一里出现 type="password",Chrome 就认为这是登录/注册表单,会主动往上套已保存的账号密码,哪怕你写了 autocomplete="off"。
注意:autocomplete="off" 在含密码框的表单上,Chrome 和 Edge 基本会忽略。这不是 bug,是它们的产品决策。
第二步:想让它填对,就老实写标准值
与其跟浏览器对抗,不如给它准确的语义。这些是 HTML 标准里定义好的值,写上之后密码管理器和手机系统都能正确识别:
<form>
<input type="text" name="username" autocomplete="username">
<input type="password" name="password" autocomplete="current-password">
<!-- 注册页 -->
<input type="password" name="password" autocomplete="new-password">
<input type="password" name="password2" autocomplete="new-password">
<!-- 其他常用 -->
<input type="email" autocomplete="email">
<input type="tel" autocomplete="tel">
<input type="text" name="code" autocomplete="one-time-code">
</form>
current-password 是"现有的密码,请帮我填",new-password 是"这是新设的密码,别乱填也别提示保存"。这两个值用对了,登录页和注册页的行为立刻就正常了。
第三步:确实不想被填,用 new-password 而不是 off
如果你的场景是后台的"修改用户密码"、或者运营配置里那些不该弹历史记录的输入框,最有效的手段是:
<input type="password" name="new_pwd" autocomplete="new-password">
Chrome 对 new-password 的处理是"不填充明文、不弹保存提示",比 off 可靠得多。普通文本框(比如搜索框、验证码)用 autocomplete="off" 通常就够了。
还有一个流传很广的技巧——给输入框加 readonly,聚焦时再移除:
<input type="text" name="captcha" readonly
onfocus="this.removeAttribute('readonly')">
它确实能挡住首屏自动填充,但代价是移动端可能不弹键盘、读屏软件体验变差,只在验证码这类小输入框上建议使用。
注意:不要用 display:none 藏一个假输入框去"骗"浏览器。Chrome 会跳过不可见元素,结果假框没被填、真框照样被填,白忙一场。真要用这招,得写成 position:absolute; left:-9999px 并配合 tabindex="-1",但这属于跟浏览器打游击,版本一更新就可能失效。
第四步:检测"是否发生了自动填充"
自动填充不一定会触发 input 事件,尤其是页面加载时的那次填充。想可靠地知道填了没,用 :-webkit-autofill 伪类配合动画事件:
@keyframes onAutoFillStart { from {} to {} }
input:-webkit-autofill {
animation-name: onAutoFillStart;
animation-duration: 0.001s;
}
document.addEventListener('animationstart', (e) => {
if (e.animationName === 'onAutoFillStart') {
console.log('被自动填充了:', e.target.name);
// 这里可以做联动,比如填充后自动校验格式
}
});
注意:这是 WebKit/Blink 系的特性,Firefox 走的是标准的 :autofill,需要另写一条规则。别指望全平台一套通吃。
第五步:修掉那片刺眼的黄色背景
Chrome 自动填充后会给输入框盖一层浅黄底色,而且优先级极高,用 background-color 盖不掉。正确姿势是内阴影加一层超长过渡:
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus {
-webkit-box-shadow: 0 0 0 1000px #fff inset;
-webkit-text-fill-color: #333;
transition: background-color 99999s ease-in-out 0s;
}
内阴影足够大就能盖住底色,transition 那条是为了防止某些版本里内阴影被重置。
第六步:顺手把移动端键盘带上
自动填充和键盘类型经常一起出问题。数字类输入建议直接给 inputmode,别用 type="number"(会带上下箭头、还能输入 e):
<input type="text" inputmode="numeric" pattern="[0-9]*" autocomplete="one-time-code">
<input type="tel" autocomplete="tel">
inputmode="numeric" 出纯数字键盘,type="tel" 出电话键盘,两者的差别在 iOS 上很明显。
小结
- 浏览器靠
type、name、label、placeholder 猜字段用途,autocomplete="off" 只是建议。
- 想填对:登录用
current-password,注册和新密码用 new-password,验证码用 one-time-code。
- 想不填:优先
autocomplete="new-password",readonly 技巧只用于小输入框。
- 检测填充用
:-webkit-autofill + animationstart 事件,别依赖 input 事件。
- 黄底用
box-shadow inset + 超长 transition 覆盖,不是改 background。
- 移动端键盘用
inputmode 和 type="tel",不要滥用 type="number"。