HTML5表单控件在旧浏览器中退化为text是标准行为,需通过功能检测+polyfill补全验证逻辑;IE9-10的required需手动校验并提示;iOS旧版placeholder需JS模拟;pattern必须显式加^$锚点且服务端二次校验。

HTML5表单控件在老浏览器里直接消失或退化成文本框
不是bug,是标准行为。IE9及更早、Android 4.3以下、iOS 6.1以前的浏览器压根不认识 type="email"、type="date" 这些值,会自动 fallback 到 type="text",连基础校验都没了。
真正要解决的不是“显示”,而是“功能补全”和“体验一致”。别指望用 CSS 修好它——底层 DOM 和事件都不一样。
- 优先检测浏览器是否原生支持:
'date' in document.createElement('input').attributes不行,得用document.createElement('input').type = 'date'; document.createElement('input').type === 'date' - 对不支持的环境,用
Modernizr.inputtypes.date或手写检测(推荐后者,避免额外依赖) - 检测到不支持时,立刻加载轻量级 polyfill,比如
flatpickr(只用于 date/datetime-local)或webshim(全量但体积大) - 注意:polyfill 后的 DOM 结构变了,原来绑在
input[type=date]上的 JS 逻辑大概率失效,得监听 polyfill 初始化完成事件(如 flatpickr 的"onClose")再操作
required 属性在 IE9-10 里没提示还阻止提交
IE9/10 虽然认识 required,但既不显示红色边框,也不弹原生提示,用户填空点提交,页面直接静默失败——表单卡住,控制台也没报错。
这不是样式问题,是 IE 对约束验证 API 的实现残缺。它调用了 checkValidity(),但不触发 invalid 事件,也不渲染伪类 :invalid。
立即学习“前端免费学习笔记(深入)”;
- 必须手动监听
submit事件,调用form.checkValidity(),返回 false 时遍历所有required字段,检查element.value.trim() === '' - 别依赖
element.validity.valueMissing,IE9 下这个属性存在但恒为false - 给空字段加临时 class(如
is-error),配合 CSS 显示红框或文字提示,别等浏览器自己来 - 如果用了 jQuery Validation 等库,确认它在 IE9 模式下启用了
ignore: [],否则可能跳过隐藏域或 disabled 元素导致误判
placeholder 在 iOS Safari 旧版里光标错位或不消失
iOS 6–8 的 Safari 渲染 placeholder 时,光标经常偏上、偏左,输入第一个字符后 placeholder 也不消失,甚至叠在文字上面。这不是 CSS 能调好的,是 WebKit 渲染层的 bug。
根本原因是 placeholder 文本节点和 input 值的排版上下文没对齐,尤其在设置了 line-height、padding 或 font-size 不一致时更明显。
- 最稳方案:禁用原生 placeholder,用 JS 模拟——创建同位置
label或span,监听focus/blur显隐 - 如果坚持用原生,强制重置相关样式:
input::-webkit-input-placeholder { line-height: normal; },并确保input和 placeholder 的font-family完全一致 - 别用
transform: translateY()微调 placeholder 位置,iOS 7 下会触发重绘异常,输入时闪屏 - 测试时真机必跑,模拟器里的 iOS 7 行为跟真机差得离谱
pattern 属性正则在不同浏览器里匹配逻辑不一致
pattern 声明的是“整个字符串必须匹配”,但 Chrome 会自动加 ^ 和 $,Firefox 早期版本不会,Safari 甚至把 \d 当普通字符处理。写 pattern="\d{3}-\d{2}" 在 Safari 里等于没写。
这问题不报错,但校验形同虚设——用户输 “123-45abc” 也能过,因为浏览器只拿你写的正则去 test(),没做全局锚定。
- 所有
pattern值必须显式写首尾锚点:pattern="^\d{3}-\d{2}$",一个都不能少 - 避免使用 \D、\s 等 Unicode 感知类符号,改用
[^0-9]、[ \t\n\r]确保跨引擎一致 - 在 JS 里做二次校验时,用
new RegExp(patternValue).test(value),别直接复用 DOM 的 pattern 属性值——它可能被浏览器转义过 - 移动端 WebView(尤其是微信内置)对 pattern 支持极不稳定,关键字段(如手机号)务必服务端再验一遍,前端只是体验优化
invalid 事件没捕获,或者 polyfill 和原生逻辑打架了。











