©
本文档使用
php.cn手册 发布
类型为 month
的 <input>
可以让你容易地创建一个方便输入年份或月份的一个 <input>
。
这个控件在各个浏览器支持都不同,目前是支持部分浏览器。在桌面上支持情况为 Chrome/Opera 和 Edge 。在移动端支持大部分现代浏览器。在其他浏览器中,这个控件会被优雅的降级到<input type="text">
.
<input id="month" type="month">
对于那些使用不支持的浏览器,Chrome / Opera月份控制如下图所示。单击右侧的向下箭头会显示日期选择器,以便您选择日期;你必须手动输入时间。
Edge的 month
看起来像这样:
值 | 表示月份和年份的DOMString,或者空的。 |
---|---|
活动 | 改变和输入。 |
支持的通用属性 | 自动完成,列表,只读和步骤。 |
IDL属性 | 值。 |
方法 | select(),stepDown(),stepUp()。 |
值
DOMString
表示输入输入的月份和年份的值。你可以设置一个默认的属性值插入到 value
里, 像这样:
<label for="bday-month">What month were you both in?</label><input id="bday-month" type="month" name="bday-month" value="2017-06">
需要注意的是显示的如期格式不同于实际的value
— 日期显示的格式将根据用户的操作系统的时区设置, 而时间的格式通常会格式化为 yyyy-MM
. 在向服务器提交上述值的时候他们看起来像这样:bday-month=1978-06
.
你也可以使用JavaScript HTMLInputElement.value
设置日期值 。
var monthControl = document.querySelector('input[type="month"]');monthControl.value = '1978-06';
与日期相关的输入乍一看很方便,它们提供了一个简单的用户界面来选择日期,并且它们将发送到服务器的数据格式规范化,而不考虑用户的本地环境。但是, 由于浏览器支持有限,所以这个 <input type="month">
还是存在兼容性问题。
我们在往下看更多关于<input type="month">
基础和更多的高级的用法
最简单的<input type="month"> 涉及到基础的 <input> 和 <label> 的元素组合, 像下面这样:
<form> <label for="bday-month">What month were you both in?</label> <input id="bday-month" type="month" name="bday-month"></form>
你可以使用min 和 max 属性 来限制用户选择日期. 在下列的例子中我们设置最小月份1900-01 最大月份到 2017-08:
<form> <label for="bday-month">What month were you both in?</label> <input id="bday-month" type="month" name="bday-month" min="1900-01" max="2017-08"></form>
结果是这样:
月份只有在2017年八月份到1900年一月可以选择 — 在这个控件里这个范围以外的月份不能滚动选择。
根据您使用的浏览器,您可能会发现超出指定值的时间可能无法在时间选择器(例如“边缘”)中选择,或者无效,但仍可用(例如Chrome)。
注意:您应该能够使用该step
属性来改变每次增加日期时跳过的天数(例如,也许您只希望使周六可选)。但是,在编写本文的任何实施过程中,这似乎并不奏效。
<input type="month">
不支持表单大小属性,如size
。你将不得不求助于CSS的大小需求。
<input type="month">不支持表单大小属性,如size。你将不得不求助于CSS的大小需求。
默认情况下,<input type="month">
不对输入的值应用任何验证。UI实现通常不会让你输入任何不是日期的东西 - 这很有帮助 - 但是你仍然可以不填写日期并提交,或者输入无效的日期(例如4月32日)。
您可以使用min
并max
限制可用的日期(请参阅anch(“设置最大值和最小值日期”)),并使用该required
属性在日期中强制填入。因此,如果您尝试提交超出设定范围的日期或空的日期字段,支持的浏览器将显示错误。
我们来看一个例子 - 在这里我们已经设置了最小和最大日期,并且还需要这个字段:
<form> <div> <label for="month">What Month would you like to visit us? (Summer months only.)</label> <input id="month" type="month" name="month" min="2017-06" max="2017-09" required> <span class="validity"></span> </div> <div> <input type="submit" value="Submit form"> </div></form>
如果您尝试使用不完整的日期提交表单(或使用设定范围外的日期),则浏览器显示错误。现在尝试玩这个例子:
这里是您不使用支持浏览器的人的截图:
这是上面例子中使用的CSS。这里我们利用:valid
和:invalid
CSS属性来根据当前值是否有效来设置输入的样式。我们必须将图标放在<span>
输入旁边,而不是输入本身,因为在Chrome中生成的内容放置在表单控件中,无法有效地进行样式化或显示。
div { margin-bottom: 10px; position: relative;}input[type="number"] { width: 100px;}input + span { padding-right: 30px;}input:invalid+span:after { position: absolute; content: '✖'; padding-left: 5px;}input:valid+span:after { position: absolute; content: '✓'; padding-left: 5px;}
重要提示:HTML表单验证是不为脚本,确保输入的数据是正确的格式的替代品。有人很容易调整HTML,使他们绕过验证,或完全删除它。也有人可能完全绕过你的HTML,直接提交数据到你的服务器。如果您的服务器端代码无法验证其接收到的数据,那么在提交格式不正确的数据(或数据太大,类型错误等)时,可能会导致灾难。
如上所述,在编写本文时使用日期输入的主要问题是浏览器支持 - 只有Chrome / Opera和Edge支持它在桌面上,以及大多数现代浏览器在手机上。举个例子,monthAndroid版Chrome浏览器中的选择器如下所示:
不支持的浏览器会优雅地降级为文本输入,但这会在用户界面的一致性(所呈现的控件将不同)和数据处理方面造成问题。
第二个问题是最严重的 - 就像我们之前提到的那样,month输入的实际值总是被格式化yyyy-mm。另一方面,通过文本输入,浏览器默认不知道日期的格式,人们可以通过多种方式写日期,例如:
mmyyyy
mm/yyyy
mm-yyyy
yyyy-mm
etc.
解决这个问题的一个方法就是pattern
在month
输入中添加一个属性。即使month
输入不使用它,文本输入后备将会。例如,请尝试在非支持的浏览器中查看以下演示:
<form> <div> <label for="month">What Month would you like to visit us? (Summer months only, yyyy-mm)</label> <input id="month" type="month" name="month" min="2017-06" max="2017-09" required pattern="[0-9]{4}-[0-9]{2}"> <span class="validity"></span> </div> <div> <input type="submit" value="Submit form"> </div></form>
如果你尝试提交它,你会看到,现在浏览器显示错误信息(并突出了输入为无效)如果您的条目不匹配的模式nnnn-nn
,在那里n
是一个数字从0到9。当然,这并未不要阻止人们输入无效日期,或者按照模式错误地格式化日期。
哪个用户将要了解他们需要输入日期的模式?
我们仍然有一个问题。
目前以跨浏览器方式处理表单中日期的最好方法是让用户在单独的控件中输入月份和年份(<select>
元素正在流行 - 请参阅下面的实现),或使用JavaScript库(如jQuery日期选择器,和jQuery timepicker插件。
在这个例子中,我们创建了两组用于选择日期的UI元素 - 一个由本地创建的选择器<input type="month">,以及一组两个<select>元素,用于在不支持本机输入的旧版浏览器中选择几个月/年。
HTML看起来像这样:
<form> <div class="nativeDatePicker"> <label for="month-visit">What Month would you like to visit us?</label> <input type="month" id="month-visit" name="month-visit"> <span class="validity"></span> </div> <p class="fallbackLabel">What Month would you like to visit us?</p> <div class="fallbackDatePicker"> <div> <span> <label for="month">Month:</label> <select id="month" name="month"> <option selected>January</option> <option>February</option> <option>March</option> <option>April</option> <option>May</option> <option>June</option> <option>July</option> <option>August</option> <option>September</option> <option>October</option> <option>November</option> <option>December</option> </select> </span> <span> <label for="year">Year:</label> <select id="year" name="year"> </select> </span> </div> </div></form>
月份是硬编码的(因为它们总是相同的),而年份值是根据当年动态生成的(请参阅下面的代码注释,了解这些功能的详细解释)。
该代码可能会感兴趣的另一部分是特征检测码-来检测浏览器是否支持<input type="month">
,我们创建了一个新的<input>
元素,设置其type
到month
,然后立即检查什么的类型设置为-不支持的浏览器将返回text
,因为这个date
类型会回到类型text
。如果<input type="month">
不支持,我们隐藏本地选择器并显示后备选取器UI(<select>
)。
// define variablesvar nativePicker = document.querySelector('.nativeDatePicker');var fallbackPicker = document.querySelector('.fallbackDatePicker');var fallbackLabel = document.querySelector('.fallbackLabel');var yearSelect = document.querySelector('#year');var monthSelect = document.querySelector('#month');// hide fallback initiallyfallbackPicker.style.display = 'none';fallbackLabel.style.display = 'none';// test whether a new date input falls back to a text input or notvar test = document.createElement('input');test.type = 'month';// if it does, run the code inside the if() {} blockif(test.type === 'text') { // hide the native picker and show the fallback nativePicker.style.display = 'none'; fallbackPicker.style.display = 'block'; fallbackLabel.style.display = 'block'; // populate the years dynamically // (the months are always the same, therefore hardcoded) populateYears();}function populateYears() { // get the current year as a number var date = new Date(); var year = date.getFullYear(); // Make this year, and the 100 years before it available in the year <select> for(var i = 0; i <= 100; i++) { var option = document.createElement('option'); option.textContent = year-i; yearSelect.appendChild(option); }}
规范
规范 | 状态 | 注释 |
---|---|---|
HTML生活标准该规范中'<input type =“month”>''的定义。 | 生活水平 |
Feature | Chrome | Edge | Firefox (Gecko) | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|---|
Basic support | 20 | 12 | No support1 | No support | 10.62 | No support2 |
Feature | Android | Chrome for Android | Edge | Firefox Mobile (Gecko) | IE Mobile | Opera Mobile | Safari Mobile |
---|---|---|---|---|---|---|---|
Basic support | (Yes) | (Yes) | (Yes) | (Yes) | ? | (Yes) | (Yes) |