原生 input[type="date"] 在 iOS Safari 和 Chrome for iOS 渲染相同但 JS 行为不一致:Safari 中 valueAsNumber 返回毫秒数,Chrome for iOS 常返回 NaN;placeholder 在 Chrome for iOS 不显示,Safari 可能渲染;这是 WebKit 内核在不同封装层的行为差异,非 bug,不应依赖 valueAsNumber 判断是否已选值。

原生 input[type="date"] 在 iOS Safari 和 Chrome for iOS 渲染相同但 JS 行为不一致
表面上看,两者都调用系统日期选择器(带下拉箭头),但底层 JS API 返回值不同:input.valueAsNumber 在 Safari 返回毫秒数,在 Chrome for iOS 常返回 NaN;placeholder 在 Chrome for iOS 完全不显示,Safari 则可能渲染。这不是 bug,是 WebKit 内核在不同封装层上的行为差异。不要依赖这些属性做关键逻辑分支,尤其别用 valueAsNumber 判断是否已选值。
input[type="date"] 在 Android WebView 和旧版 Firefox 中直接退化为文本框
Android 4.4–6.0 的 WebView、Firefox 桌面版(至今仍不支持原生日历弹窗)、部分国产浏览器内核,会把 type="date" 当作普通 text 处理:无弹窗、无格式校验、checkValidity() 总返回 true。检测方式不能只靠 typeof input.type === 'string',得实测:
const el = document.createElement('input');<br>el.type = 'date';<br>const supportsDate = el.type === 'date' && el.checkValidity();失败时必须 fallback 到 JS 日历库(如 flatpickr),且服务端必须二次校验格式。
桌面端 Chrome/Edge/Firefox 对 datetime-local 支持分裂,Safari macOS 直到 16.5 才完整支持
iOS 16.4 之前、macOS Safari 16.4 及更早版本,datetime-local 渲染为纯文本输入框,且不会触发 invalid 事件——用户输错格式也不会提示,提交后字段直接从 FormData 中消失(不是空字符串,是根本不存在)。它的合法值格式严格为 YYYY-MM-DDTHH:MM(无秒、无时区),手动输入 2024-05-01 不补 T00:00 就算无效。若业务需要时间精度,优先用两个分离的 date + time,或统一降级为 text + 正则校验 /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}$/。
样式重置对 input[type="date"] 几乎无效,appearance: none 在 Safari 会禁用弹窗
你无法用 CSS 可靠地修改原生日期控件的内部结构:Safari 不响应 padding、font-size(除非 ≥16px 且 min-height: 44px),Firefox 根本不渲染弹窗。更关键的是,appearance: none 在 Safari 上不是“隐藏下拉箭头”,而是彻底禁用点击唤起日历的功能。正确做法是包裹一层容器,用自定义按钮触发 JS 日历,再把值同步到隐藏的原生 input 或 FormData 中;所有样式控制都落在容器和按钮上,而非原生控件本身。
立即学习“前端免费学习笔记(深入)”;
真实项目里最常被忽略的一点:日期字段为空时,不是传"",而是整个字段名从表单数据中消失——这会让后端接收逻辑出错,尤其是用 req.body.fieldName 直接取值的 Node.js 代码。必须在服务端做存在性判断,而不是只判空。



















