我的 Input框 不可能这么可爱

2019-11-19    seo达人

作者:陈大鱼头

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?)$/

1

第二步:重点功能

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"> 的子元素来实现,而不是再写一大堆的操作函数来实现。



总结


分享本文至:

日历

链接

blogger

蓝蓝 http://www.lanlanwork.com

存档