『极限版』不掺水,用纯 CSS 来实现超飒的表单验证功能

去年的时候写过一篇文章 纯CSS实现表单验证 ,在发表之后不久就有网友跟鱼头说,打算拿我这篇文章作团队内部分享。

当时听到这个消息之后,在屏幕前的鱼头笑咧了嘴,但这位童鞋的下一段内容,就让我马上笑不起出来了。

不过因为初始化状态是这样的:

https://fish-pond-1253945200.cos.ap-guangzhou.myqcloud.com/img/css/css-form-validation/invalid.png

所以希望我能够改一下,改成这样:

https://fish-pond-1253945200.cos.ap-guangzhou.myqcloud.com/img/css/css-form-validation2/1.png

只有在进行输入且输入内容不对的时候才展示错误信息。

https://fish-pond-1253945200.cos.ap-guangzhou.myqcloud.com/img/css/css-form-validation2/2.jpg

这位童鞋:“所以这功能能实现吗?”

我:“。。。。。。”

既然有童鞋这么看得起鱼头,还打算拿鱼头的 DEMO 来作内部分享,那总得硬着头皮来实现这个功能。

首先我们来看一下最终成果图:

https://fish-pond-1253945200.cos.ap-guangzhou.myqcloud.com/img/css/css-form-validation2/3.gif

DEMO 在线查看地址:https://codepen.io/krischan77...

各位读者童鞋,来跟鱼头一起拆分下功能实现:

HTML

首先我们来看 HTML 的源码

<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>

这里面的 HTML 标签都比较常规,但是我们要注意下 <input /> 所携带的几个属性:

required

<input required/> 中的 required 是一个布尔属性,用来告诉浏览器这个 <input> 是否是必填项。

我们来康康DEMO:

<section class="section">
    <h1>请输入信息</h1>
    <form action="/userInfo">
        <input name="text" type="text" required />
        <input name="submit" type="submit" value="提交信息">
    </form>
</section>

效果如下:

https://fish-pond-1253945200.cos.ap-guangzhou.myqcloud.com/img/css/css-form-validation2/4.gif

兼容性如下:

https://fish-pond-1253945200.cos.ap-guangzhou.myqcloud.com/img/css/css-form-validation2/7.png

原生样式体验也是不错的。

pattern

再来 pattern 属性。

<input pattern=""> 用于校验输入 value 是否有效。

我们康康DEMO:

<section class="section">
    <form>
        <h1>请输入 我爱鱼头</h1>
        <input name="text" type="text" pattern="我爱鱼头"  required />
        <button type="submit">提交信息</button>
    </form>
</section>

效果如下:

https://fish-pond-1253945200.cos.ap-guangzhou.myqcloud.com/img/css/css-form-validation2/5.gif

兼容性如下:

https://fish-pond-1253945200.cos.ap-guangzhou.myqcloud.com/img/css/css-form-validation2/6.png

不得不感慨,原生组件的能力也是很强的。

CSS

接下来我们康康CSS的部分,源码如下:

: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;
}

我们重点介绍以下几个 CSS 选择器:

:invalid 与 :valid

判断有效性的伪类选择器(:valid:invalid)匹配有效或无效,<input><form>元素。

:valid伪类选择器表示值通过验证的<input>,这告诉用户他们的输入是有效的。

:invalid伪类选择器表示值不通过通过验证的<input>,这告诉用户他们的输入是无效的。

例子如下:

<style>
    input:valid {
        outline: 1px solid green;
    }

    input:invalid {
        outline: 1px solid red;
    }
</style>
输入文字:
<input type="text" pattern="[\w]+" required />
<br />
输入电话号码:
<input type="tel" pattern="[0-9]+" required />

效果如下:

https://fish-pond-1253945200.cos.ap-guangzhou.myqcloud.com/img/css/selectors-4/valid-demo.gif

兼容性如下:

https://fish-pond-1253945200.cos.ap-guangzhou.myqcloud.com/img/css/selectors-4/valid.png

:placeholder-shown

:placeholder-shown 伪类 在 <input><textarea> 元素显示 placeholder text 时生效。

例子如下:

<style>
    input {
        border: 2px solid black;
        padding: 3px;
    }

    input:placeholder-shown {
        border-color: silver;
    }
</style>
<input placeholder="Type something here!">

效果如下:

https://fish-pond-1253945200.cos.ap-guangzhou.myqcloud.com/img/css/selectors-4/placeholder-shown-demo.png

兼容性如下:

https://fish-pond-1253945200.cos.ap-guangzhou.myqcloud.com/img/css/selectors-4/placeholder-shown.png

实现逻辑

有了上面的几个 <input /> 属性以及 css 选择器的伪类说明,那么这个纯CSS实现表单验证的功能就变得简单多了。

我们先来整理下功能要求:

  1. 初始化状态:不展示提交按钮以及错误提示
  2. 清空输入状态:不展示提交按钮以及错误提示
  3. 输入错误状态:输入框输入错误时,展示错误提示
  4. 输入正确状态:输入框输入正确时,隐藏错误提示,展示提交按钮

初始化状态

首先我们知道,初始化 时,是没有提示信息的,所以提示信息可以直接隐藏,至于提交按钮,我们就利用 :invalid 来隐藏,因为初始化的 input.value 内容是不匹配的。所以我们有:

<style>
    .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;
    }
</style>
<input data-title="账号" placeholder="请输入正确的账号" pattern="\w{6,10}" name="account" type="text" required />
<input data-title="密码" placeholder="请输入正确的密码" pattern="\w{6,10}" name="password" type="password" required />
<span class="f-tips">请输入正确的密码</span>

清空输入状态

清空输入状态 也比较简单,可以直接用伪类选择器 :empty 来判断,只要内容为空,则隐藏错误信息,所以我们有:

input[required]:empty + span {
    display: none;
}

输入错误状态

初始化 时已经隐藏了错误信息,而 初始化 其实也是依赖于 输入错误 这个状态,不过好在我们有伪类选择器 :focus ,它表示获得焦点的元素(如表单输入),所以我们有:

input[required]:focus:invalid + span {
    display: inline;
}

虽然我们不能通过 输入错误 这个状态来处理,但是我们可以监听用户聚焦的行为来实现。

但是这么做有个弊端,就是当我在另外一个输入框输入信息的时候,错误提示也会消失,所以我们还需要判断是否有 placeholder,输入了 value ,自然没有 placeholder ,所以我们有:

input[required]:invalid:not(:placeholder-shown) + span {
    display: inline;
}

输入正确状态

当完成上述三个状态的实现之后, 输入正确 的状态就可以不用编写了,因为不匹配错误的,就是匹配正确。

总结

一个完整的 纯CSS表单功能 就这么完成了,DEMO地址在这:

https://codepen.io/krischan77...

由于实际项目的复杂度,这个功能不一定直接用起来,但是里面的知识点,思路我们都是可以复用的。

不得不感慨,如今 htmlcss 的能力变得强大了起来,只要我们愿意散发思维,一定能编写出更多有意思,有价值的效果。

欢迎大家多方尝试!

参考资料

  1. whatwg 4.10.5 The input element
  2. 纯CSS实现表单验证
  3. 『真香警告』这33个超级好用的CSS选择器,你可能见都没见过。
  4. CSS 选择器

鱼头的Web海洋
鱼头的Web海洋

Kris不只是一只鱼头

959 声望
3.1k 粉丝
0 条评论
推荐阅读
用神奇的 form 验证 API 来优化你的表单验证
鱼头曾在 『极限版』不掺水,用纯 CSS 来实现超飒的表单验证功能 一文中分享过一个花里胡哨的 纯 CSS 的表单验证功能 。虽然仅仅依赖 CSS 是无法满足我们的日常开发需求的,但是配合着各种原生的 form 验证 API ...

陈大鱼头5阅读 2.2k

从零搭建 Node.js 企业级 Web 服务器(十五):总结与展望
总结截止到本章 “从零搭建 Node.js 企业级 Web 服务器” 主题共计 16 章内容就更新完毕了,回顾第零章曾写道:搭建一个 Node.js 企业级 Web 服务器并非难事,只是必须做好几个关键事项这几件必须做好的关键事项就...

乌柏木60阅读 5.9k评论 16

再也不学AJAX了!(二)使用AJAX ① XMLHttpRequest
「再也不学 AJAX 了」是一个以 AJAX 为主题的系列文章,希望读者通过阅读本系列文章,能够对 AJAX 技术有更加深入的认识和理解,从此能够再也不用专门学习 AJAX。本篇文章为该系列的第二篇,最近更新于 2023 年 1...

libinfs39阅读 6.1k评论 12

封面图
从零搭建 Node.js 企业级 Web 服务器(一):接口与分层
分层规范从本章起,正式进入企业级 Web 服务器核心内容。通常,一块完整的业务逻辑是由视图层、控制层、服务层、模型层共同定义与实现的,如下图:从上至下,抽象层次逐渐加深。从下至上,业务细节逐渐清晰。视图...

乌柏木39阅读 7k评论 6

CSS 绘制一只思否猫
欢迎关注我的公众号:前端侦探练习 CSS 有一个比较有趣的方式,就是发挥想象,绘制各式各样的图案,比如来绘制一只思否猫?思否猫,SegmentFault 思否的吉祥物,是一只独一无二、特立独行、热爱自由的(&gt;^ω^&lt...

XboxYan41阅读 2.8k评论 14

封面图
还在用 JS 做节流吗?CSS 也可以防止按钮重复点击
举个例子:一个保存按钮,为了避免重复提交或者服务器考虑,往往需要对点击行为做一定的限制,比如只允许每300ms提交一次,这时候我想大部分同学都会到网上直接拷贝一段throttle函数,或者直接引用lodash工具库

XboxYan34阅读 2.2k评论 2

封面图
【关于Javascript】--- 正则表达式篇
基础知识一、元字符 {代码...} 二、量词 {代码...} 三、集合 字符类 {代码...} 四、分支 {代码...} 五、边界 开始结束 {代码...} 六、修饰符 {代码...} 七、贪婪模式和非贪婪模式js默认贪婪模式即最大可能的匹配...

Jerry35阅读 2.9k

Kris不只是一只鱼头

959 声望
3.1k 粉丝
宣传栏