input[type="date"]的min/max属性仅接受YYYY-MM-DD格式,缺位、错位或含时间均失效;动态设置须用setAttribute或dispatchEvent;旧版Safari需手动触发更新;超限值不会自动清空,且无法阻止手动输入。

min 和 max 属性只认 YYYY-MM-DD,错一位就失效
浏览器对 input[type="date"] 的 min 和 max 极其严格:必须是形如 "2026-08-04" 的字符串。任何偏差都会被静默忽略——日历不灰、输入不拦、提交也不报错,但 checkValidity() 会返回 false。
-
new Date().toISOString().split('T')[0]看似稳妥,但在某些时区下可能跳到前一天(比如 UTC+8 区用户用toISOString()得到的是前一日的日期) -
"2026-8-4"或"2026/08/04"都无效;月份和日期必须两位补零 -
"2026-08-04T00:00"含时间部分 → 属性被丢弃 - 后端返回的
"04/08/2026"或"20260804"也完全不识别
动态设置必须用 setAttribute,直接赋值 .min = '...' 不可靠
在 Safari(尤其 iOS ≤ 15.5)和部分旧版 Chrome 中,直接写 input.min = "2026-08-04" 不会刷新日历 UI,用户仍能点选超限日期。真正生效的方式只有:
- 用
input.setAttribute('min', '2026-08-04')—— 触发 DOM 属性变更,强制重绘 - 或赋值后手动触发更新:
input.dispatchEvent(new Event('input', { bubbles: true })) - 如果
input.value已存在且超出新max,浏览器不会自动清空,必须显式判断并重置:if (input.value && input.value > input.max) input.value = ''
用户仍能手动输入超限日期,min/max 不是安全锁
min/max 只影响日历弹窗和提交校验,完全不限制键盘输入、粘贴、删除重输等行为。Chrome/Firefox 提交时会拦截并提示,但 Safari 默认不触发校验。
- 必须监听
change或input事件做实时检查:if (new Date(e.target.value).getTime() - 对 Safari 建议加兜底
blur监听,因其change在移动端触发不稳定 - 若需强约束(比如禁用手动输入),得加
readonly或拦截keydown,但会牺牲可访问性
联动日期时,min/max 清空逻辑不能漏
做“结束日期不能早于开始日期”这类联动时,只设 end.min = start.value 是不够的。一旦用户清空了开始日期,end.min 必须同步清除,否则 end 将永远无法选择任何值(因为 min 被卡在一个已不存在的日期上)。
立即学习“前端免费学习笔记(深入)”;
- 监听
start的change:若start.value为空,必须执行end.removeAttribute('min') - 监听
end的change:若end.value && start.value && end.value ,调用 <code>end.setCustomValidity('结束日期不能早于开始日期')并立即end.reportValidity() - 服务端必须二次校验——所有客户端限制都可被绕过
min/max 是 UI 辅助,不是防线。真正起作用的永远是那几行校验逻辑 + 服务端兜底。



















