表单字段的四件事:51个站的邮箱框,全写上的只有6个
本文目录
- 浏览器本来准备替这一格做哪几件事?
- 这一轮量了什么,为什么要先去一次重?
- 邮箱那一格,四件事都写全的有几个?
- autocomplete用得最多的那个取值,为什么是off?
- 搜索框为什么是全场最不像框的那一个?
- 同一个站里的两个邮箱框,写法为什么不一样?
- 平台给的那一页,和自己后加的那个框,差在哪?
- 校验这件事,页面到底交给了谁?
- 这一轮尺子失效了三次
- 第一次:同一个框被数了四遍
- 第二次:读表单id,读回来一个输入框
- 第三次:跟踪像素往页面里塞了160个输入框
- 这些数字有几个边界
- 照着改,先动哪四处?
- 常见问题解答
- 写不写autocomplete,对SEO排名有影响吗?
- 我的表单是JavaScript接管提交的,还有必要写这些属性吗?
- type=email的浏览器校验太松,写了也拦不住乱填的邮箱,还写它干嘛?
- 搜索框的autocomplete写成off,到底该不该?
- 怎么快速查一遍自己站上这些属性写没写?
- 这些属性会不会因为浏览器差异而不生效?
- 权威参考资料
摘要:把55个独立站的191个页面逐页拆开,数了一遍每个输入框身上写了什么。同一个站里重复渲染的框先合并,最后剩下1902个控件、422个真要用户打字的字段。收邮箱的那一格有160个,分布在51个站上——写了type=email的86.9%,写了autocomplete=email的只有45.6%,四件事(类型、代填、必填、名字)全都写上的42.5%。按站算更难看:51个站里,所有邮箱框都写全的只有6个。整批数据里autocomplete出现最多的取值不是任何一个字段名,是off。
页面上绝大多数东西是站点在单向说话:标题在说、图片在说、价格在说。只有一个地方反过来——输入框。那是用户往里写字的地方,也是这一页上唯一一处需要页面提前交代清楚的地方:这一格要什么。
交代给谁?不是给用户。用户看一眼旁边那行小字就知道该填邮箱。要交代的是浏览器。浏览器手里握着一整套现成的本事:调出带 @ 的键盘、把用户存过的地址一键填进去、在提交前拦下一个明显不成立的邮箱、告诉密码管理器这是新密码不是旧密码。这些本事一件都不需要你写代码,但每一件都需要你在标签上写一句话。不写,它就当你不需要。
这一轮就是去数这句话有没有人写。
浏览器本来准备替这一格做哪几件事?
先把机制摆清楚,后面的数字才有落点。一个输入框上能写的东西不少,真正会触发浏览器动作的是下面这几个,它们各管各的,互相替代不了。
| 写在哪儿 | 浏览器拿它干什么 | 不写会怎样 |
|---|---|---|
type | 决定用哪种控件、手机上弹哪种键盘、提交前做哪种最基本的格式检查 | 当成一行普通文本,什么都不管 |
autocomplete | 认出这一格要的是邮箱、名字还是收货地址,把用户存过的值填进来 | 只能靠猜,猜不准就不填 |
required | 空着不让提交,并且把这件事同步进无障碍树 | 星号只有眼睛看得见 |
inputmode | 在type不变的前提下换一套软键盘 | 手机上继续弹全键盘 |
pattern与maxlength | 提交前挡掉明显不合规的输入 | 全部推给后端和那段JavaScript |
这五样东西有个共同点:它们都是声明,不是行为。你写下来,浏览器照做;你不写,页面照样长得一模一样,用户也照样能填——只是那些本来免费的帮助全都不会发生。视觉上没有任何代价,这正是它们容易被漏掉的原因。
还有一个容易混的点。MDN的autocomplete取值清单里,取值不是随便起的名字,是标准里定死的一份枚举。HTML标准的表单控件章节一共定义了65个取值,去掉section、shipping、billing这类修饰词和on、off两个开关,真正的字段名是54个。写在里面的浏览器认,写成autocomplete="phone-number"这种自己发明的,等于没写。
这一轮量了什么,为什么要先去一次重?
样本沿用手上那批英文独立站:55个站,每站抓首页、一个商品页,再从首页现场找出联系页和账号页各一个,凑成4个页面。实际拿到200并且能解析的是191个页面。取不回来的33个里,15个撞429被限流,13个是404(多数是账号页那条约定路径根本不存在),剩下几个是400、403、500。这些页一律不进分母,不凑数。
每个页面上,把所有input、select、textarea全都读出来,连同它的type、name、id、autocomplete、required、pattern、maxlength、inputmode、placeholder,以及它的名字到底是从label、aria-label还是placeholder上来的,一并记下来。原始数据是4393个控件实例。
然后就撞上了第一件麻烦事。
mackweldon的首页上有6个邮箱框,商品页上也是6个,联系页7个,登录页6个。翻开一看,其中5个每一页都长得一模一样:登录用的、找回密码用的、注册用的,全被主题塞进了同一个抽屉,抽屉挂在每一个页面上。按页面数,这一个框会被数四遍;哪个站的页面抓得多,哪个站的写法就自动获得更大的权重。
所以先去重:同一个站里,控件类型、name、autocomplete、required、名字来源、名字文本、占位符全都一样的,算作同一个字段的多次渲染。4393个实例合成1902个字段。合并的量不小——去重后的字段里,有31.3%是在三个及以上页面上重复出现的。
这个口径本身也是个发现:一个站的表单写得好不好,多数时候不是页级决策,是它主题里那几份模板的事。这一点后面还会再撞见一次。
1902个控件里,绝大多数是商品页上的颜色尺码单选钮和各种勾选项。真正要用户打字的(text、email、search、tel、password、number、textarea这些)是602个。这602个里还得再剔掉180个,剔掉的原因放在后面那节尺子失效里讲,最终422个,来自54个站。
邮箱那一格,四件事都写全的有几个?
先看最能横向比的那一格。422个字段里,能判定为收邮箱的有160个,来自51个站——比例之高说明了一件事:这批站上唯一一件人人都在做的事,是收邮箱。同一件事、五十多种实现,正好当尺子用。至于这个框本身该怎么设计、什么时候弹出来才不招人烦,邮件弹窗那篇与邮件列表从零养起那篇都拆过,本文只管它在源码里说了什么。
四件事分开看:
| 这一格写没写 | 写了的 | 占比 |
|---|---|---|
type="email" | 139 | 86.9% |
| 有个正经名字(label或aria,不是只有占位符) | 142 | 88.8% |
required或aria-required | 116 | 72.5% |
autocomplete="email" | 73 | 45.6% |
| 四件全写上 | 68 | 42.5% |
单看每一项都不算灾难,凑到一起就塌了一半。而且组合分布很集中:写全的68个之外,第二多的是35个只差autocomplete那一项,第三多的是24个既没autocomplete也没required。四件事全都没写的有7个。
换个算法更难看。按站算,把一个站上所有邮箱框都要求写全,51个站里做到的只有6个:brooklynbedding、casper、dollarshaveclub、hellotushy、oclean、stanley1913。反过来,一个都没写全的站有16个。
顺带把这一格的名字文本也数了一遍,因为它经常被当成随手可以变的东西。160个邮箱框里,写了占位符的122个,原样不同的写法41种,忽略大小写和末尾标点后归一化,还剩27种:Email、Email Address、Your email address、Enter your email here...、your@email.com。可及名称那一列同样是34种原样、23种归一。同一个概念,在同一批页面上有二十多种叫法——这件事对用户没影响,对拿名字去认字段的程序有影响,也正是首页正文可读性那一轮实测里数过的另一层:那次数的是这一格有没有名字,这次数的是它写没写清楚自己要什么。
autocomplete用得最多的那个取值,为什么是off?
把范围放大到全部1902个控件,写了autocomplete的只有164个,8.6%。这个数字本身不奇怪——单选钮和勾选项本来就用不上它。奇怪的是取值分布。
164个里,取值合法的105个,写成off的55个,写on的2个,自己发明取值的2个(password和phone-number,标准里都没有这两个名字)。也就是说,整批数据里autocomplete这个属性出现最多的单一取值不是email,是off:email 73次,off 55次,第三名current-password只有7次。
更值得念一遍的是覆盖面。标准给了54个字段名,覆盖到姓名分段、地址分级、信用卡有效期、生日拆成年月日、一次性验证码。这55个站实际用到的是13个:bday-day、bday-month、bday-year、country、current-password、email、family-name、given-name、name、new-password、postal-code、sex、tel。标准写了54格,行业只用了两成半。
那55个off也不是随便关的。按用途拆开,29个是搜索框,其余散落在邮箱、密码、姓名上。搜索框关掉浏览器的历史下拉,理由通常说得通:站点自己做了联想,两层下拉叠在一起确实难看。但邮箱框上那6个off就不太讲得通了——用户存过的邮箱不给填,省下的是他自己那几秒。
这里得说句公道话,off的语义在标准里也有点尴尬:它本意是“这一格不适合自动填充”,浏览器并不保证照做,密码管理器更是长期无视它。所以写off常常连它想要的效果都拿不到,只是让这一格彻底失去了被正确识别的机会。
搜索框为什么是全场最不像框的那一个?
把字段按用途分成几个桶,横着对比一次,差距一眼就看出来了。
| 这一格在要什么 | 个数 | 站数 | type写对 | 写了autocomplete | 写了必填 |
|---|---|---|---|---|---|
| 邮箱 | 160 | 51 | 86.9% | 50.0% | 72.5% |
| 密码 | 26 | 23 | 100% | 57.7% | 65.4% |
| 姓名 | 38 | 26 | 100% | 42.1% | 55.3% |
| 留言 | 21 | 20 | 95.2% | 4.8% | 28.6% |
| 电话 | 12 | 12 | 66.7% | 50.0% | 16.7% |
| 数量 | 18 | 15 | 83.3% | 5.6% | 5.6% |
| 搜索 | 80 | 45 | 30.0% | 33.8%(全是off) | 1.2% |
密码框百分之百写对了type,因为写错就会把密码明文显示出来,第一次自测就会被发现。邮箱框写对86.9%,因为写错了手机上不弹 @ 键,测试的人多半也会察觉。写对的那些,几乎都是写错了立刻能看见的那些。
搜索框恰恰相反。type写成search还是text,页面上看不出任何区别——两者的差别只在于移动端的回车键变成“搜索”、部分浏览器会给一个清除小叉、以及它在无障碍树里的身份。看不出区别,就没人改,于是80个搜索框里56个还是type=text。至于那1.2%的必填,倒是合理,搜索框本来就不该拦人。
顺着这条线往后看还有一层:站内搜索页那一轮实测发现,四十个电商站里查得到和查不到长得几乎一模一样。入口这一格身份模糊,结果那一页身份也模糊,两头都没人当成一件正经事来写。
搜索这一格另有一层账。它是站上被点得最多的输入框之一,也是搜索框设计那篇反复讲过的高转化入口;而它在源码里恰恰是身份最模糊的那个。移动网页与App上提交按钮的那次对照量过它的外形差异,这一轮量的是它在标记层的自我介绍——两边的结论正好接上:这个框的实现,被当成了纯视觉问题。
同一个站里的两个邮箱框,写法为什么不一样?
这是本轮最干净的一次自基线。跨站比较总有借口——技术栈不同、团队规模不同、上线年份不同。那就在同一个站里比:同一个站的两个邮箱框,写法一致吗?
51个站里,有两种及以上不同邮箱框写法的是43个。这43个里,四件事写得前后不一致的有37个,86.0%。
不一致的形态高度一致。举几个(用四位数字表示四件事,顺序是type、autocomplete、required、名字):
- allbirds:首页、商品页、联系页上的订阅框都是1010,登录页上的那个是1111;
- brooklinen:首页与联系页的订阅框1001,登录页1111;
- baseus:首页1001,联系页0000,登录页1111;
- bollandbranch:三个订阅框全是1011,登录页1111。
规律很扎眼:登录页那个框永远是写全的,首页页脚那个订阅框永远缺一两样。不是同一批人写的,也不是同一天写的。
平台给的那一页,和自己后加的那个框,差在哪?
顺着上一节往下追,把字段按“是谁加上去的”分三档,差距就不是几个百分点了。
| 这个框来自哪儿 | 字段数 | 站数 | 写了autocomplete | 写了必填 | type写对 | 有正经名字 |
|---|---|---|---|---|---|---|
| 站点自己的表单 | 284 | 54 | 49.3% | 56.3% | 89.3% | 86.6% |
| 提交给第三方的表单 | 37 | 10 | 8.1% | 18.9% | 87.5% | 94.6% |
| 不在任何表单里 | 101 | 37 | 6.9% | 5.9% | 33.3% | 89.1% |
三档里最惨的不是第三方,是第三档。那101个字段压根不在任何一个form元素里——搜索框、弹层里的邮箱格、商品页上那个到货通知框,全靠JavaScript接管。这一档里type写对的只有三分之一,autocomplete 6.9%,必填5.9%。一个连自己属于哪张表单都没交代的框,自然也不会交代自己要什么。
第三方那一档有意思在别处:名字写得最好(94.6%),autocomplete最差(8.1%)。这两个数放一起,画像很清楚——那是营销工具生成的订阅表单,它非常在乎表单在视觉上和无障碍上过得去,但完全不在乎浏览器能不能替用户把邮箱填进去,因为那对它的转化归因没有任何帮助。第三方脚本自己会变这件事在这里同样成立:那一档的写法什么时候改、改成什么样,不由你定。
再按页面类型看一遍,同一件事从另一个角度冒出来:
| 页面 | 字段数 | 写了autocomplete | 写了必填 | type写对 |
|---|---|---|---|---|
| 平台默认的登录页 | 29 | 72.4% | 72.4% | 96.6% |
| 注册页 | 24 | 58.3% | 58.3% | 91.7% |
| 站内链接过去的账号页 | 106 | 56.6% | 58.5% | 81.8% |
| 首页 | 164 | 47.0% | 40.9% | 77.3% |
| 联系页 | 211 | 27.0% | 30.8% | 75.6% |
| 商品页 | 216 | 33.8% | 34.7% | 73.0% |
顺序基本是按“这一页有多少是平台自带的”排下来的。登录页那29个字段里,name属性写着customer[email]、id写着CustomerEmail的一大片——那是电商平台默认主题里的原件,从模板里出厂就带着autocomplete和required。首页页脚那个订阅框、商品页那个到货通知框,才是各家自己后来加的。
所以本轮真正的结论不是“大家不懂”,而是:这些属性写没写,跟开发者知不知道关系不大,跟这个框是从哪儿来的关系极大。平台默认的模板替你写好了,你自己拼的那个没人替你写。这条线同样解释了为什么robots.txt里那些指令三分之一是白写的、为什么响应头里躺着248个死字段——出厂默认值的惯性,比任何一份最佳实践都强。
校验这件事,页面到底交给了谁?
把422个要打字的字段过一遍校验类属性,数字冷得有点好笑:
- 写了
required的142个,33.6%;另有31个只写了aria-required,也就是只告诉了读屏软件,没告诉浏览器; - 写了
pattern的21个,5.0%; - 写了
maxlength的33个,7.8%; - 写了
inputmode的6个,1.4%。
那31个只写aria-required的挺说明问题。写这一行的人显然知道无障碍这回事——无障碍改造那份清单里这一条排得很靠前——但他把它当成了一条无障碍要求,而不是一条功能声明。同一件事写在required上,读屏软件照样读得到,浏览器还顺手帮你拦一次空提交。
再看表单这一级。360张去重后的表单里,有可见可填项的“真表单”120张,其中54张写了novalidate——45.0%的真表单,明确关掉了浏览器的内建校验。
关掉不见得是错。MDN关于客户端校验的那篇写得很清楚:浏览器自带的那个气泡提示样式改不动、文案不能自定义、多语言站上它按浏览器语言走而不是按页面语言走。想把错误提示做成自己的样子,第一步就得关掉它。这条路径完全正当。
问题在于关掉之后有没有补上。错误提示那一篇算过另一笔账:后端明明知道用户错在哪,页面上却只剩四个字。两件事连起来看是同一条链:先把浏览器能说的那句话关掉,再把自己该说的那句话省掉,最后用户面对的就是一个不肯说明理由的框。
inputmode那1.4%值得单独说一句。它是这批属性里成本最低的一个——MDN的inputmode说明里那一行属性,加上去就能让手机上弹出的键盘换一套。数量框、邮编框、验证码框都用得上。全样本422个字段里写了的6个,其中4个还是数量框。移动端那根手指本来就够忙了,多按几次切换键盘这件事,没人算进过成本。
这一轮尺子失效了三次
按老规矩,量之前先量尺子。这一轮尺子坏了三次,三次都是在写稿之前抓到的,每一次都会改掉结论。口径变更那篇讲的是同一条线上前后不可比,这里是同一次读数里分母被污染,性质一样:数字不会喊疼,只有你自己去翻明细才知道它坏了。
第一次:同一个框被数了四遍
就是前面讲的抽屉问题。不去重的话,主题里那几个隐藏表单会按页面数量翻倍,谁的页面抓得多谁的权重就大。按签名去重之后,“要打字的字段”从一堆实例收敛到422个,邮箱框从300多个收敛到160个。所有百分比都是在去重之后算的。
第二次:读表单id,读回来一个输入框
脚本第一版在44个页面上直接崩了,报的是“这个值上没有replace方法”。查下去才发现,HTML标准给form元素开了个后门:表单里那些控件的name会被挂到表单对象上,而且优先级高过表单自己的属性。商品页那张加购表单里通常有个<input name="id">装着变体ID,于是读form.id读回来的是那个输入框本身。全样本里有275张表单实例中招,出自33个站。改成getAttribute('id')之后重跑,那44个页面全部回来了。
第三次:跟踪像素往页面里塞了160个输入框
第一版算出来“提交给第三方的表单”有318个要打字的字段,其中242个来自两个站。翻开一看,parachutehome的商品页上有一张form,action指向https://www.facebook.com/tr/,整张表display:none,里面160个type=text的输入框,name是id、ev、dl、rl、ts、ud[external_id]这种——那是跟踪像素把自己的请求参数做成了输入框。它们既没有可及名称也没有占位符,从头到尾没打算给人看。
判据因此收紧了一道:从没可见过、又没有任何说明文字的字段,不算“用户要填的字段”。这一刀切掉180个,其中166个出自那个像素。切完之后,“第三方表单”这一档从318个字段变成37个,画像也跟着反转——原来算出来的是“第三方连名字都不写”(17.2%),真值是“第三方名字写得比谁都好”(94.6%),差的是autocomplete。如果没抓到这一刀,整节结论会写反。
这些数字有几个边界
三条,都得摆在明处。
第一,读数只是一个时刻的快照。页面载入后等9秒左右读一次,这是本轮的口径。另外挑了29个首页做对照:什么都不做、只多等20秒,17.2%的页面form数会变、20.7%的页面可填控件数会变;再替用户点一下那个订阅或搜索入口,56.5%的页面控件数会变,全样本可填控件从42个涨到70个。所以这里所有的百分比,量的是“不点、只等一会儿”那个状态下的页面。换个等法,分母就换了。
第二,样本偏平台。55个站里相当一部分跑在同一个电商平台上,前面那条“平台默认写得好”的结论,本质上是这批平台的默认模板写得好,换一套自研前端未必成立。
第三,这一轮只看声明,没看行为。写了type="email"不等于后端真的验邮箱,写了autocomplete="email"也不保证浏览器一定填得进去——它还要看这一格在不在一个form里、页面有没有别的东西挡着。声明是必要条件,不是充分条件。
照着改,先动哪四处?
按投入产出排,四步,前两步半小时能做完。
第一步,把站上所有收邮箱的框找出来,一个一个补齐四件事。找法很土但管用:全站搜type="text"加email这个词,再搜一遍页脚模板、弹层模板、到货通知模板。本轮51个站里只有6个通过了这一关,这一步的性价比高得离谱。四件事分别是type="email"、autocomplete="email"、required、一个真正关联上的label。
第二步,把autocomplete从“想起来才写”改成模板里的默认项。结账那一套尤其要注意收货与账单要分别加shipping和billing前缀,这件事结账流程那一篇已经拆得很细。做之前先照着标准的54个字段名过一遍,别自己发明取值——本轮就抓到phone-number和password这两个不存在的名字。
第三步,清点一遍不在任何form里的输入框。这一档的各项指标全场最差,而且它们多半是最近两年加的组件。搜索框、订阅弹层、到货通知,只要还在用div拼,就顺手把type和autocomplete补上,成本几乎为零。下拉框那篇讲过同一个道理的另一面:能用原生控件解决的,别自己造。
第四步,如果你关掉了novalidate,去看看错误提示补上了没有。关掉本身没问题,关掉之后什么都不补才是问题。顺手把inputmode加到数量框和邮编框上,两分钟的事。
再往前一步的话,值得把这件事塞进组件库而不是塞进checklist。本轮那86%的站内不一致说明得很清楚:靠人记,记不住;靠模板,才记得住。保哥自己那批工具页上的输入框,也是先补进模板才彻底不再漏的——之前每次新加一个页面就漏一次,checklist上写得再清楚都没用。
顺带一提,这件事跟AI时代那套讨论也接得上。智能体读的是无障碍树而不是页面截图,而type、required、名字这三样恰好就是那棵树上的节点属性;给代理适配站点这件事,起点不在于加什么新标记,而在于把二十年前就有的这几个属性写全。语义化标签那篇的老结论在这里依然成立:机器读到的东西,从来只有你写下来的那部分。
常见问题解答
写不写autocomplete,对SEO排名有影响吗?
没有直接影响,搜索引擎不会因为你写了autocomplete给你加分。它影响的是转化和可用性:用户少打十几个字符,表单完成率就不一样。真要说和搜索的关系,只有间接的一条——这些属性同时也是无障碍树上的节点信息,而读页面的程序越来越多地依赖那棵树。把它当成转化优化去做,别当成排名手段。
我的表单是JavaScript接管提交的,还有必要写这些属性吗?
有,而且更有必要。JavaScript接管的是提交那一步,type、autocomplete、required管的是提交之前的每一秒:弹哪种键盘、能不能一键代填、空着提交时提不提示。本轮那101个不在任何form里的字段,各项指标全场最差,正是因为团队默认“反正JS全管了”。
type=email的浏览器校验太松,写了也拦不住乱填的邮箱,还写它干嘛?
它确实很松,只要有 @ 就放行,MDN的input type=email文档里明确写了这一点。但它真正的价值在别处:手机上弹带 @ 的键盘、告诉浏览器这一格可以用存过的邮箱去填、在无障碍树里表明身份。校验只是它顺手做的第四件事。
搜索框的autocomplete写成off,到底该不该?
如果你自己做了搜索联想,写off是合理的,能避免两层下拉叠在一起。但要知道两件事:一是浏览器不保证照做,密码管理器基本无视它;二是别把这个习惯顺手复制到邮箱、姓名、地址那些框上。本轮55个off里有6个落在邮箱框上,那几个纯属抄模板抄过头了。
怎么快速查一遍自己站上这些属性写没写?
不用装工具。打开控制台跑一句document.querySelectorAll('input,select,textarea'),把type、name、autocomplete、required打出来看一眼就够了。要注意两个坑:一是同一个框可能在多个页面重复出现,别重复计数;二是页面上可能有跟踪像素注入的隐藏输入框,判据是“从没可见过又没有任何说明文字”,那些不算你的字段。
这些属性会不会因为浏览器差异而不生效?
type、required、pattern的支持度早就没有问题了。inputmode在主流移动浏览器上都能用。autocomplete的差异主要在“填不填”的策略上——各家浏览器和密码管理器有自己的启发式判断,你写对了它未必百分之百填,但你不写它基本就只能猜。web.dev那份登录表单最佳实践把这套判断讲得比较全,值得照着核一遍。
权威参考资料
本文标题:《表单字段的四件事:51个站的邮箱框,全写上的只有6个》
本文链接:https://zhangwenbao.com/form-field-declaration-audit.html
版权声明:本文原创,转载与引用请注明作者与原文链接。许可协议: CC BY 4.0