input type="month" 的 value 必须严格为 YYYY-MM 格式,如“2026-09”,否则控件清空、checkValidity() 返回 false;min/max 也需同格式才生效;JS 赋值应使用 year + "-" + String(month).padStart(2, "0");服务端须二次校验且注意空字符串。

input type="month 的 value 必须是严格 YYYY-MM 格式,否则控件清空、校验失败、提交为空——这不是浏览器 bug,是规范强制要求。
value 必须是 "2026-09",不是 "2026/09" 也不是 "2026-9"
浏览器只接受四位年份 + 短横线 + 两位补零月份(01–12)的字符串。任何偏差都会导致输入框变空,且 checkValidity() 返回 false:
-
"2026-09"✅ 合法,显示正常 -
"2026/09"❌ 清空,不报错 -
"2026-9"❌ 清空(parseInt("9", 10)是 9,但字符串格式不匹配) -
"2026年09月"❌ 清空,连校验都绕过
JS 动态赋值时别用 toISOString().slice(0,7)——它受本地时区影响,可能在 UTC+8 下返回上月;稳妥写法是:year + "-" + String(month).padStart(2, "0"),其中 month 是 0–11 的整数。
min/max 限制必须写全 "2026-01",单写 "01" 或 "2026" 没用
min 和 max 属性只有在完整 YYYY-MM 格式下才生效,浏览器对格式错误静默忽略(不警告、不限制、也不报错):
立即学习“前端免费学习笔记(深入)”;
-
min="2026-01"✅ 有效 -
min="01"❌ 被忽略 -
min="2026"❌ 被忽略 -
min="2026-1"❌ 被忽略(月份缺前导零)
想限制“仅能选 2026 年全年”,必须同时设 min="2026-01" 和 max="2026-12"。服务端不能信任前端限制,仍需二次校验提交的 value 是否在业务允许范围内。
拿到的永远是字符串,不是 Date 对象
input.value 是只读字符串,不是日期、不是数字、更不是可直接用于计算的对象:
-
new Date(input.value)→Invalid Date(Date构造函数不支持YYYY-MM) - 正确转为当月第一天:
const [y, m] = input.value.split('-').map(Number); new Date(y, m - 1, 1) - 后端收到的仍是
"2026-09",Java 需@DateTimeFormat(pattern = "yyyy-MM"),PHP 需DateTime::createFromFormat("Y-m", $val) - 数据库查询别写
WHERE MONTH(created_at) = '2026-09'——类型错配,应转为范围:BETWEEN '2026-09-01' AND '2026-09-30'
Safari 旧版本和 WebView 会 fallback 成无校验文本框
截至 2026 年 9 月,iOS 16.4 / macOS 13.3 以上才稳定支持 type="month";旧版 Safari 完全不识别,直接降级为普通 type="text",用户能输任意内容(如 "abc"、"2026-13"),且无内置校验:
- 不能只靠
min/max做业务约束 - 样式几乎不可定制:
::-webkit-inner-spin-button等伪元素无效,无法隐藏年份或禁用滚动 - 若产品需季度标识、多语言月份名、或禁用某几个月(如只允许 Q3),建议直接用
flatpickr等轻量 JS 选择器,并统一处理输入/输出格式
最易被忽略的点:空字符串 "" 是合法初始值,也是用户未选择时的提交值——后端不做判空就直接解析,大概率抛异常或查全表。



















