浏览器表单自动填充调研
参考
1.浏览器表单自动填充问题
2. 如何更好的去除谷歌浏览器中 input 自动填充背景
3. 设置 input 控件自动填充的样式
4. 聊聊:autofill和autocomplete自动填充
总结
- 自动填充保存用于登录此网站的密码,这个动作是需要用户手动确认的,如果用户没有保存则不会有,网站的这个功能主要是为了存储密码,如果是个普通表单,那么不会被浏览器记录(chrome 对设置了 name 的表单会有记录)
- 自动填充分两种,一种是直接添加到表单中(非交互自动填充),一种是提供下拉选择(交互自动填充)
- firefox 中如果一个域名下只有一个账号密码记录,那么会自动添加到表单中
- chrome(非无痕模式) 中一个域名下无论有多少个账号密码记录,都会自动添加最近使用的到表单中
- safari 不会自动添加到表单中,需要下拉选择
- 表单不在 Form 中,可以使用 自动填充,但是不能保存自动填充值
- 必须存在至少一个 type=“password” 的表单
- 只存在一个 type=“password” 的表单 会被自动填充密码
- 存在一个 type=“text” 表单 + 一个 type=“password” 表单,type=“text” 在上边会被填充,type=“text” 在下边不会被自动填充
- 存在一个 type=“password” 表单 + 多个 type=“text” 表单则 type=“password” 上边最近的 type=“text” 会被自动填充
- 如果存在 多个 type=“password” 且不在一个 Form 中则各论各的,在一个 Form 中则只有第一个 type=text + type=password 结构会有正常的自动填充提醒,其余的只有 type=password 的表单会有密码自动填充提醒(safari 除外),且不同浏览器表现不一致
- readonly 和 disabled 属性会影响自动填充, name 的值对是否自动填充影响不大,但是 chrome 上如果一个 name=‘abc’ 的表单有了提交,那么下次再遇到 name=‘abc’ 的表单,会有历史记录的提示
- autoComplate 的语义
- autoComplete=“off” 无效,很多浏览器在很多情况下都是不支持这样设置来关闭自动提示的,参考 https://www.zhangxinxu.com/wordpress/2022/09/css-autofill-html-autocomplete-off/
- autoComplete=‘new-password’ 可以阻止一部分情况下的自动回填
- autoComplete 属性的值还有很多,但是兼容性很差,参考 https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete ,
- 如何禁用自动填充 – 主要禁用 “自动添加到表单中” 这个行为
- type=“password” 的表单增加 readonly 属性,然后在表单的 focus 事件中将 readonly 置为 false;不建议用,因为我们用的组件库组件有可能借用了 input 标签的 onFocus,两者叠加不好处理
- autocomplete=‘new-password’ 可以禁用“自动添加到表单中” 这个行为,type=text 表单的 focus 也不会出现下拉选项(safari 除外), 但是 type=password 的表单 focus 会出现下拉,且选中后,type=text 的表单也会被填充(firefox 除外)
- 在 type=text 和 type=password 之间加入一对 input 表单,并将其样式设置为隐藏(设置 display: none 对于 chrome 来说不会得到预期的结果,需要设置成决定定位,然后将节点定位到看不见的地方),来使得浏览器这两个隐藏的表单自动填充,(注意:chrome 要实现同样的效果需要叠加 autocomplete=‘new-password’ 一起来实现)
<Form onSubmit={onSubmit} onReset={onReset} colon={true} labelWidth={0}>
<FormItem name="username">
<Input
clearable={true}
placeholder="请输入账户名"
autocomplete="new-password"
/>
</FormItem>
{/* <input/> 是 react 原生组件不是组件库组件,所以不影响组件库收集表单数据 */}
<input type="text" name="no-text" style={{position: "absolute"}} />
<input type="password" name="no-pwd" style={{position: "absolute"}} />
<FormItem name="password">
<Input
type="password"
clearable={true}
placeholder="请输入密码"
autocomplete="new-password"
/>
</FormItem>
<FormItem>
<Button theme="primary" type="submit" block>
登录
</Button>
</FormItem>
</Form>
- 如何给单个 type=text 表单增加 自动填充行为
- 在 type=text 之下增加一个 type=password 的表单,这个表单要隐藏 UI(还是不能通过 display: none 隐藏,否则在 safari 上不会出现密码填充下拉框,可以使用 position: absolute 定位到看不见的地方)
- 需要注意的是这个 type=text 表单仅能自动填充 账户密码信息中的账户.
<Form onSubmit={onSubmit} onReset={onReset} colon={true} labelWidth={0}>
<FormItem name="username">
<Input clearable={true} placeholder="请输入账户名" />
</FormItem>
{/* <input/> 是 react 原生组件不是组件库组件,所以不影响组件库收集表单数据 */}
<input type="password" name="no" style={{ position: "absolute" }} />
<FormItem>
<Button theme="primary" type="submit" block>
登录
</Button>
</FormItem>
</Form>
- 如何设置 input 自动填充样式
- nput 设置内阴影为 预期的颜色即可(不透明)
- input 高度设置为 0,背景剪裁方式设置为 content-box 这样浏览器自动回填的区域颜色即使有值也不会显示出来,然后消失的 input 高度通过 padding 撑开,padding 多大由开发者决定
/* 方案 1. input 设置内阴影为 预期的颜色即可(不透明) */
input:autofill {
box-shadow: 0 0 0px 1000px white inset;
}
/* 方案 2. input 高度设置为 0,背景剪裁方式设置为 content-box 这样浏览器自动回填的区域颜色即使有值也不会显示出来,然后消失的 input 高度通过 padding 撑开,padding 多大由开发者决定 */
.form-input input {
height: 0;
background-clip: content-box;
padding: 1.2em 0.5em;
}
- 不同浏览器版本,表现也有不一致的可能