- 作者:陈大鱼头
- github:KRISACHAN
<input />
标签是我们日常开发中非常常见的替换元素了,但是最近在刷 whattwg 跟 MDN 的时候发现 跟 <input />
有很多相关的属性,选择器都没怎么用过,所以就开篇文章来整理一下一些比较有趣或者实用的知识点。
本篇文章默认大家已经知道 <input />
标签的基本用法,不会做过多的基础说明~
没想到,这些选择器居然跟 input …
到写文章为止,根据最新的 drafts 指出,一共有 3 大类,16 种跟 input 相关的选择。其实都挺有用的,善用它们,会让我们的用户体验更加美好。
下面我们来分享一下这 3 大类选择器的作用:
第一类:控制系(Input Control States)
选择器 | 作用 |
---|---|
:enabled | 选择可使用状态的 <input /> 元素 |
:disabled | 选择不可使用状态的 <input /> 元素 |
:read-only | 选择不可编辑状态的元素(不仅仅是 <input /> ) |
:read-write | 选择可编辑状态的元素(不仅仅是 <input /> ) |
:placeholder-shown | 选择 placeholder text 显示时的元素 |
:default | 选择在 <button> ,<input type="checkbox" /> ,<input type="radio" /> , 以及 <option> 上的默认状态 |
第二类:输出系(Input Value States)
选择器 | 作用 |
---|---|
:checked | 选择处于选中状态的 <input type="radio" />
|
:indeterminate | 选择状态不确定的表单元素与 <progress>
|
第三类:侦查系(Input Value-checking)
选择器 | 作用 |
---|---|
:blank | 选择处于空值时的 <input> ,暂未被浏览器支持 |
:valid | 选择验证通过的表单元素 |
:invalid | 选择验证不通过的表单元素 |
:in-range | 选择处于指定范围内的 <input />
|
:out-of-range | 选择不处于指定范围内的 <input />
|
:required | 选择必填的表单元素 |
:optional | 选择选填的表单元素 |
:user-invalid | 选择用户输入但值非法时的 <input /> ,暂未被浏览器支持 |
可怕,除了选择器,居然还跟这些属性有关系
<input>
除了有很多相关的选择器,结合不同的 type 还有不同的属性可以供使用。他们的作用如下:
属性 | 作用 |
---|---|
maxlength | 可输入的最大长度 |
minlength | 可输入的最小长度 |
size | 输入框的长度 |
readonly | 输入框是否只读 |
required | 输入框是否必填 |
multiple | 输入框是否可以多选 |
pattern | 输入框验证规则 |
min | 可输入的最小值 |
max | 可输入的最大值 |
step | 输入框每次的增量 |
list | 输入框绑定的可选值数据 |
placeholder | 输入框预选文字 |
实战
通过上面的三类说明,我们大致了解了 <input />
标签的相关信息,但是你们以为我是来列 list 的吗?
当然不是,还有实操啊~
纯 CSS 实现表单提交功能
首先我们来看个效果图
上面的效果就是一个纯 CSS 实现的表单提交功能,这是怎么实现的呢?下面我们直接看源码,然后一步一步地来分拆(不想看的可以直接 CV 下面的源码自己做测试~)
<style>
:root {--error-color: red;}
.form > input {margin-bottom: 10px;}
.form > .f-tips {color: var(--error-color);
display: none;
}
input[type="text"]:invalid ~ input[type="submit"],
input[type="password"]:invalid ~ input[type="submit"] {display: none;}
input[required]:focus:invalid + span {display: inline;}
input[required]:empty + span {display: none;}
input[required]:invalid:not(:placeholder-shown) + span {display: inline;}
</style>
<form class="form" id="form" method="get" action="/api/form">
账号:<input data-title="账号" placeholder="请输入正确的账号" pattern="\w{6,10}" name="account" type="text" required />
<span class="f-tips"> 请输入正确的账号 </span>
<br />
密码:<input data-title="密码" placeholder="请输入正确的密码" pattern="\w{6,10}" name="password" type="password" required />
<span class="f-tips"> 请输入正确的密码 </span>
<br />
<input name="button" type="submit" value="提交" />
</form>
第一步:写好基础结构
首先我们来把基础结构给写好,代码如下:
<style>
:root {--error-color: red;}
.form > input {margin-bottom: 10px;}
.form > .f-tips {color: var(--error-color);
display: none;
}
</style>
<form class="form" id="form" method="get" action="/api/form">
账号:<input data-title="账号" placeholder="请输入正确的账号" pattern="\w{6,10}" name="account" type="text" required />
<span class="f-tips"> 请输入正确的账号 </span>
<br />
密码:<input data-title="密码" placeholder="请输入正确的密码" pattern="\w{6,10}" name="password" type="password" required />
<span class="f-tips"> 请输入正确的密码 </span>
<br />
<input name="button" type="submit" value="提交" />
</form>
扫一眼,嗯,挺简单的,都是常用的东西。咦,不对,这个 pattern
是什么东西?
在这里我们重点分享下 pattern
这个属性,这是一个用来验证 input[value]
是否合法的属性,里面的内容就是匹配 value 的,语法便是正则的语法,例子如下:
<label>
<!--
当前 pattern 的内容就是验证 input[name="part"] 的 value 的,其规则如同里面的正则一样,匹配 input[name="part"] 的 value 是否是一个数字 + 3 个大写字母
-->
<input pattern="[0-9][A-Z]{3}" name="part" />
</label>
当然,不同的 input[type]
也会默认带有相应的 pattern
,例如 input[type="email"]
就是默认匹配了以下规则:
/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/
第二步:重点功能
input[type="text"]:invalid ~ input[type="submit"],
input[type="password"]:invalid ~ input[type="submit"] {display: none;}
input[required]:focus:invalid + span {display: inline;}
input[required]:empty + span {display: none;}
input[required]:invalid:not(:placeholder-shown) + span {display: inline;}
上面便是核心交互的实现。
首先第一个 class 就是保证了在两个输入框不通过的时候隐藏,就是当输入框值为空或者不符合验证规则,则隐藏提交按钮。
第二个,第三个 class 则是控制当用户在输入框输入内容时,如果不符合验证规则,则显示错误信息,否则则隐藏。
第四个 class 则是用过 placeholder 是否存在来控制错误信息的显隐,如果 placeholder 不显示,则证明用户正在输入,错误信息则根据用户输入的值来判断是否显隐,否则则隐藏。
状态切换
上面我们有提到一个选择器 :indeterminate
,这个是用于选择状态不确定的表单元素与 <progress>
,玩过扫雷的人都知道,右击除了可以选择红旗,还可以选择问号,就是选中,但不确定;又跟 promise
的 pending
状态类型,介于 resolve
与 reject
之间。
多了 :indeterminate
会给我们带来很多很有趣的体验。
首先我们来看看它的使用案例。
基础使用法
先看效果
代码如下:
<style>
body {
background: #333;
color: #fff;
padding: 20px;
text-align: center;
}
input {
margin-right: .25em;
width: 30px;
height: 30px;
}
label {
position: relative;
top: 1px;
font-size: 30px;
}
</style>
<form>
<input type="checkbox" id="checkbox">
<label for="option"> 点击左边 </label>
</form>
<script>
'use strict';
checkbox.addEventListener('click', ev => {if (ev.target.readOnly) {ev.target.checked = ev.target.readOnly = false;} else if (!ev.target.checked) {ev.target.readOnly = ev.target.indeterminate = true;};
});
</script>
这里面其实没有什么复杂的实现,只是做了个中间态的判断,就非常轻松的实现了 radio 的三种状态切换。
秀到头皮发麻法
先看效果
(此天秀效果来自于 Ben Szabo 的 codepen,有兴趣的可以仔细研究下,我何时才能有大佬这么优秀,嘤嘤嘤~)
输入框绑定的可选值
先看效果
其实代码很简单:
<input type="text" list="names" multiple />
<datalist id="names">
<option value="kris">
<option value="陈大鱼头">
<option value="深圳金城武">
</datalist>
<input type="email" list="emails" multiple />
<datalist id="emails">
<option value="chenjinwen77@foxmail.com" label="kris">
<option value="chenjinwen77@gmail.com" label="kris">
</datalist>
<input type="date" list="dates" />
<datalist id="dates">
<option value="2019-09-03">
</datalist>
这里原理就是通过 <input list="dates" />
来绑定需要下拉显示的数据列表 <datalist id="dates">
。
那么当我们要实现输入联想的时候,也可以通过修改 <datalist id="dates">
的子元素来实现,而不是再写一大堆的操作函数来实现。
总结
其实 <input />
标签还有很多有趣的功能是可以挖掘的,不同的类型,结合不同的选择器与属性,是可以有更多让人为之惊叹的体验的。如果你有兴趣的话,不妨多开开脑洞,亲自动手实现一些有趣的功能,或者有什么有趣的想法也可以在下方给鱼头留言或者加鱼头微信 “krisChans95” 来畅谈。
如果你也喜欢探讨技术,或者对本文,本系列有任何的意见或建议,你可以扫描下方二维码,关注微信公众号“ 鱼头的 Web 海洋
”,随时与鱼头互动。欢迎!衷心希望可以遇见你。