聊聊:autofill和autocomplete自动填充

这篇文章发布于 2022年09月19日,星期一,22:59,归类于 Web综合。 阅读 4350 次, 今日 17 次 6 条评论

 

表单填充示意

一、关于表单自动填充

表单自动填充是个好功能,因为可以省去用户自己输入的麻烦。

比方说一个name属性值是email的输入框,聚焦点击后,可能就出现下图所示的邮箱列表:

邮件列表

奇怪,怎么出现了手机号?

应该是某个产品的 name 属性值是email,但是却支持手机号输入,然后被浏览器记住了。

大多数时候,用户很喜欢这个功能。

但是有时候,用户并不需要。

比方说验证码输入框,每次的验证码都是随机的,是没有任何理由是需要浏览器进行记忆的。

以及,如果采用了浏览器的自动填充input输入框的样式,比方说背景色,就会变成浏览器默认的自动填充背景色,如下图所示(我的Windows系统下是淡蓝色):

浏览器自动填充样式示意

而这种浏览器默认的色值往往和产品的主题色并不一致,产品或者设计师往往会要求进行重置。

于是,此时,表单自动填充的行为就变得不美丽了,希望取消。

浏览器也确实提供了取消自动填充的HTML属性autocomplete以及匹配自动填充状态的:autofill伪类,既然浏览器有了能力,似乎问题到此结束了。

然而非也,又很多时候,明明设置了autocomplete="off",但是依然有自动填充。

咦?这是怎么回事呢?

没有什么怎么回事,就是浏览器的策略,浏览器说不要你觉得,而是我觉得 !

我不要你觉得

我们可以在 caniuse 上看到对各个浏览器那种情况下 autocomplete="off" 无效的描述,具体如下:

  • Chrome浏览器在用户使用了自动填充功能的情况下,autocomplete="off" 无效。
    Chrome off情况下
  • Safari浏览器在 username,email 和 password文本框的时候,关闭自动填充无效。
    Safari部分支持说明
  • Firefox浏览器则是在登录表单中无法使用autocomplete="off"关闭自动提示。
    Firefox部分支持说明

所以,问题就变成了,autocomplete off 无效怎么办?

二、autocomplete off 无效怎么办

这个要分情况。

一种是阻止非交互自动填充,一种是阻止交互式自动填充。

阻止非交互自动填充

所谓非交互自动填充,指的是无需用户操作,一进入页面,浏览器就帮你把对应的数据填充好了。

例如账号和密码是比较常见的自动填充能力。

例如有如下所示的HTML代码:

<form>
    账号:<input name="email" placeholder="手机号或邮箱">
    密码:<input type="password" name="pwd">
</form>

如果你有让浏览器记住当前域名下的密码,则一进入页面就有可能会看到类似下面这样的自动填充:

自动填充效果

此时,你给输入框元素,哪怕给外面的 <form> 元素(如果有)设置autocomplete off都是无效的,那该怎么办?

· 根据我的测试,效果比较好的,是一种名为“李代桃僵”的方法,就是在表单元素的前面插入两个替身使者,就像下面这样的:

<!-- 浏览器认为的 -->
<input disabled style="opacity: 0;position: absolute; top:-99px">
<input type="password" disabled style="opacity: 0;position: absolute; top:-99px">
<!-- 用户看见的 -->
账号:<input name="email" placeholder="手机号或邮箱">
密码:<input type="password" name="pwd">

· 对password密码输入框设置autocomplet="new-password"在Firefox浏览器下有效,不过在Chrome浏览器下无效。

· 还可以给密码输入框设置readonly属性,在第一次按下的时候移除来规避自动填充:

<input type="password" name="pwd" readonly autocomplete="off" onMouseDown="this.removeAttribute('readonly')">

虽然上面的方法可以让默认进入的时候没有自动填充,但是,当用户点击输入框的时候,又会出现类似下面的烦人提示,该如何规避呢?

保存的密码

无解!

没必要规避,密码的系统呼出框建议就无视好了。

如果非要解决,也可以,使用普通input输入框覆盖在password输入框上面,颜色设置为透明,光标颜色设置为文字颜色,隐藏边框和背景色。

代码示意:

<input class="cover">
<input type="password" name="new-password">
.cover {
    position: absolute;
    -webkit-text-fill-color: transparent;
    border-color: transparent;
    background: none;
}
.cover,
.cover ~ input {
    font-family: Consolas, Monaco, "Courier New", monospace;    
}

然后密码输入框的value和覆盖的输入框实时同步即可。

此时,focus密码框就不会有系统的密码管理提示了。

眼见为实,您可以狠狠地点击这里:密码输入框的自动填充和系统提示关闭demo

阻止自动填充

这个的解决相对简单点,多出现在相同name属性值的输入框,或者兄弟输入框有着历史相同name或者类型数据记录的时候。

此时,要么使用 autocomplete="off",要么使用 autocomplete="new-password"

如果上面两个属性值都无效,那就……可以整个在线demo,我可以帮大家看下怎么回事。

例如一开始那个name属性值是email的输入框的下拉提示,在我设置 autocomplete="off" 之后,再次点击输入框,再也看不到下拉出现了。

GIF示意如下:

autocomplete off示意

三、新时代的autocomplete

在过去,autocomplete支持的属性值比较单纯,就 on 和 off,autocomplete支持的属性值有好几十个。

对,你没看到,有好几十个,容易理解的有username,new-password,current-password等,长得像妖魔鬼怪的像是cc-name,bday-day,impp等。

完整属性值大家可以参见MDN文档

算了,想了想,还是自己整理个表格吧,看起来方便些。

属性值 释义
off 浏览器不再自动填入或选择值。
name 输入框期待是人物全名。如果不是全名,还可以使用下面这些属性值。honorific-prefix(前缀或抬头,如”Mrs.”, “Mr.”, “Miss”, “Ms.”, “Dr.”, 或”Mlle.”)、given-name(给定名字或开始名)、additional-name(中间名)、family-name(家庭名或最后名)、honorific-suffix(名字后缀,如”Jr.”, “B.Sc.”, “PhD.”, “MBASW”, 或”IV”)、nickname(昵称)
email 邮箱地址
username 用户名或账号名
new-password 新密码。浏览器可能会出现自动生成的随机密码选项。
使用生成的安全密码
current-password 用户当前密码
one-time-code 用来验证用户信息的一次性代码,例如手机验证码
organization-title 工作抬头,或者个人在组织中的级别。像是高级前端开发工程师这种。
organization 组织名称。
street-address 街道地址,无需包含国家或城市信息。
address-line1
address-line2
address-line3
每一行的街道地址,只有当上面的street-address不存在的情况下,这些才有用。
address-level4 颗粒度最细的地址,共四级。
address-level3 至少包括三层行政级别。
address-level2 地址中需要出现两个行政管理级别。
address-level1 地址最前面的行政级别,在中国就是指省了。
country 国家或地区代码。
country-name 国家或地区名称。
postal-code 邮政编码。
cc-name 打印在支付工具(如信用卡)上或与之相关联的全名。
cc-additional-name 信用卡等支付工具上的开始名(相当于中文名字的名,老外的名在前面,叫做first name也叫given name)。
cc-family-name 信用卡等支付工具上的中间名
cc-family-name 信用卡等支付工具上的家族名(相当于中文名字的姓)
cc-number 识别付款方式的信用卡号或其他号码,如帐号。
cc-exp 付款方式到期日,通常格式为“MM/YY”或“MM/YYYY”。
cc-exp-month 付款方式到期的年份。
cc-exp-month 付款方式到期的月份。
cc-csc 支付工具的安全代码;在信用卡上,这是卡背面的三位数验证码。
cc-type 支付工具的类型(如“Visa”或“Master Card”)。
transaction-currency 进行交易的货币。
transaction-amount 以“交易货币”为指定货币的付款单交易金额。
language 首选语言,使用 BCP 47 语言标签 中给定的合法值。
bday 完整的出生日期。
bday-day 出生日期所在月份的日期。
bday-month 出生日期所在的月份。
bday-year 出生的年份
sex 性别认同……
tel 完整的手机号码,包括国家的编码。如果手机号码分多个输入框填写,可以使用下面这些值:tel-country-code(国家编码,中国是0086)、tel-national(不含国家代码的整个电话号码,要包括省内区号,例如021-xxx88250)、tel-area-code(区号)、tel-local(电话或手机号码不含区号的部分)
tel-extension 电话号码中的电话分机代码,如酒店的房间或套房号码或公司的办公室分机。
impp 即时消息协议端点的URL,例如“xmpp:username@example.net”.
url URL网址,例如主页或公司网站地址
photo 代表人、公司或其他信息的图片的URL地址。

我自己测试了几个属性值,比方说 username,发现和设置属性值为on 效果一样:

<input name="code" autocomplete="username">

如果是设置的随机的乱七八糟的值,则和 off 效果一样:

<input name="code" autocomplete="xxxxx">

这个特性表现值得深思……

四、自动填充样式的重置

下图是火狐下的自动填充效果:

CSS :autofill伪类可以匹配已经自动填充的输入框,因此,可以用来重置自动填充时候的高亮背景色,例如下图是火狐下的自动填充效果,是非常骚气的淡黄色。

Firefox下的自动填充样式示意

因为是背景色,很多开发人员自然而然会想到使用类似下面的代码进行重置:

:-webkit-autofill { background-color: transparent; }
:autofill { background-color: transparent; }

结果很遗憾,上面的代码并不能重置系统的自动填充背景色。

其实仔细一想就好理解了,既然浏览器要保证输入框高亮背景色能够显示,肯定是不可能被普普通通一个CSS背景样式就被重置的。

所以这里,想要让自动填充的高亮背景色不显示,需要使用其他方法,目前业界用的比较多的就是使用巨大的box-shadow内阴影进行覆盖,代码示意:

:-webkit-autofill { box-shadow: inset 0 0 0 2000px #fff; }
:autofill { box-shadow: inset 0 0 0 2000px #fff; }

此时,自动填充带来的高亮背景色就不可见了。

五、结尾的絮叨

大多数情况下,输入框的自动填充行为我们无需处理,用户并不在意输入框颜色变了,或者出现一些样式不一致的提示效果。

但是,有一种情况则不然,那就是输入框本身有下拉行为的时候。

例如开发者自定义了一套Autocomplete组件列表功能,结果用户focus输入框的时候,自定义的列表和系统的自动完成列表同时出现了,就像下面这样:

同时出现提示

这个时候就不能不处理了,方法一般就是设置autocomplete属性值是off,如果不行再试试new-password,还是不行试试删除name属性值。

最后,再提一嘴。

autocomplete 的策略浏览器是不断变化的,我写文章这会儿,和我两年前研究的结果已经发生了变化,Chrome有段时间off属性值就是摆设,普通的自动填充就无法规避,但是现在看,已经没有这个问题了。

所以,说不定过两年,本文那些填充问题,说不定也会消失不见。

好了,以上就是本文的全部内容。

如果你觉得内容还不错,欢迎转发,感谢阅读!

(本篇完)

分享到:


发表评论(目前6 条评论)

  1. White说道:

    为啥,我这里的type为text的input,有的会出现autocomplete提示框,有的又不会。。。同是Chrome浏览器

  2. 去他*的说道:

    当年是搞什么编辑器来着,(只是拿调软键盘),然后死家伙的自动填充……

    后来才知道代码编辑器用 textarea 的多…

  3. 代码如诗如画说道:

    输入框背景花里胡哨的情况,怎么规避自动填充的背景。。。

  4. 鼙鼓说道:

    所以浏览器这种怪异的表现是出于安全考量吗?

    • PRebrith说道:

      浏览器都希望提升占有率,提升粘性
      提升粘性最有效的方式就是掌握用户的密码