您只需使用 HTML 属性就可以完成令人印象深刻的表单验证。您可以使用 CSS 选择器使用户体验变得简洁明了。但这确实需要一些 CSS 技巧才能使一切都变得完美!
(您可以) 使标签看起来像占位符
首先:**始终使用真正的 元素。** 仅此一项就是许多表单都无法做到的 UX 考虑因素。占位符是对有效输入的建议,例如在标有“城市”的输入中输入“Tulsa”。
我认为如果表单很短且模式很明显(例如注册或登录),您可以使用占位符视觉模式,但使用真实标签代替。
以这样的表单为例……
<form action="#0" method="post">
<div>
<input type="text" id="first_name" name="first_name">
<label for="first_name">First Name</label>
</div>
<!-- ... --->
</form>
您使用 <div>
form {
max-width: 450px;
// positioning context
> div {
position: relative;
// Looks like placeholder
> label {
opacity: 0.3;
position: absolute;
top: 22px;
left: 20px;
}
}
}
您不需要进行任何棘手的游标操作,因为它已经全部按语义连接。如果他们点击标签占据的区域,它将激活输入。如果他们点击输入,它将激活输入。两者都正确。
技巧是将输入放在前面(语义上很好),这样您就可以隐藏焦点上的标签
form {
/* ... */
> div {
> input[type="text"],
> input[type="email"],
> input[type="password"] {
&:focus {
& + label {
opacity: 0;
}
}
}
}
}

使某些输入成为必填项
您可以在表单上进行的最简单的验证可能是使用 required
属性来要求填写字段。没有比让浏览器(如果可以)来完成它更快的捕捉错误的方式了!
<input
required
type="text"
id="first_name"
name="first_name">

明确地指示有效的输入值
让用户知道已正确输入字段。浏览器可以通过 :valid
CSS 选择器为我们提供此信息
form {
> input[type="text"],
> input[type="email"],
> input[type="password"] {
// show success!
&:valid {
background: url(images/check.svg);
background-size: 20px;
background-repeat: no-repeat;
background-position: 20px 20px;
// continue to hide the label
& + label {
opacity: 0;
}
}
}
}
}

在这种情况下,:valid
确保满足必填条件,但该选择器也有助于验证输入类型。
显示有关类型验证的提醒
您还可以要求输入的值为特定类型,例如 email
或 number
。这里有 所有类型的示例。
<input id="email" name="email" required="" type="email">
该输入既是必填项,也需要是有效的电子邮件地址格式。让我们为此做一些 UX 工作
- 当字段获得焦点时,告诉用户相关要求
- 提醒他们该字段没有有效的其他值
但是……当输入为空时,不要显示任何提醒。也就是说,不要假设无效状态。这有点烦人,而且不必要地消极。为了做到这一点,我们需要知道输入是否为空。
子技巧!测试输入是否有值
我们想用 :valid
和 :invalid
做一些事情,但我们不想在输入有值之前就使用 :invalid
并操之过急。
有没有 CSS 选择器可以测试输入是否为空?实际上没有!您可能会认为 :empty
就是它,但它不是。这用于匹配像
… 这样的容器元素,里面什么都没有。输入本身就是无内容元素。
技巧是确保输入有一个占位符值,然后
input:not(:placeholder-shown) {
}
我们演示中没有真正使用占位符,但一个空格的值可以工作
<input type="text" placeholder=" ">
:placeholder-shown
对我们来说非常有用!它基本上是用于测试输入当前是否有值的秘密选择器。
但是,IE 或 Firefox 没有支持,这尤其难以绕过。对于这样的新功能,@supports
通常是一个救星,但是……
/* This doesn't work */
@supports (input:placeholder-shown) {
input:not(:placeholder-shown) {
}
}
您不能将 @supports
用于选择器,只能用于属性/值(例如 @supports (display: flex)
)
在 JavaScript 中测试占位符支持非常容易
var i = document.createElement('input');
if ('placeholder' in i) {
}
但是,似乎没有简单的方法来测试 :placeholder-shown
。因此……这可能需要等待更深入的浏览器支持才能在大型生产环境中使用。
假设有很好的支持,逻辑将如下所示……
form {
> div {
> input[type="text"],
> input[type="email"],
> input[type="password"] {
// When input is...
// 1. NOT empty
// 2. NOT in focus
// 3. NOT valid
&:invalid:not(:focus):not(:placeholder-shown) {
// Show a light reminder
background: pink;
& + label {
opacity: 0;
}
}
// When that invalid input becomes in focus (and also still isn't empty)
&:invalid:focus:not(:placeholder-shown) {
// Show the more robust requirement instructions below.
& ~ .requirements {
max-height: 200px;
padding: 0 30px 20px 50px;
}
}
}
// <input> ~
// <label> ~
// <div class="requirements">
.requirements {
padding: 0 30px 0 50px;
color: #999;
max-height: 0;
transition: 0.28s;
overflow: hidden;
color: red;
font-style: italic;
}
}
}

您可以创建强大的验证
不仅仅是 required
或 type="email"
(以及类似的),您还可以客户端验证诸如长度(例如最小密码长度或生物文本区域中的最大字符数)之类的事情,甚至可以进行完全的正则表达式验证。
这里有关于此主题的文章。假设您想要像这样进行密码要求
- 至少 6 个字符
- 至少 1 个大写字符
- 至少 1 个小写字符
- 至少 1 个数字
您可以像这样进行操作
<input pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{6,}" type="password" id="password" name="password" required placeholder=" ">

演示
我在这里保留了 :placeholder-shown
的内容,这使得它在 Firefox 和 IE 中不太好用非常好,因为现在支持了,除了 IE 11 之外。
更多
- Mihael Konjević:表单中的内联验证——设计体验
- 不同输入类型的 Datalist
- 年鉴——
:required
,:valid
,:invalid
,:placeholder
,:placeholder-shown
这里有很多很棒的技巧,但我不知道
opacity: 0
是否是标签的最佳方法。这会阻止您点击先前输入的文本,因为(不可见的)标签会覆盖它。display: none
或pointer-events: none
怎么样?您也可以将标签从页面左侧踢开,或者使用剪切() 技巧。在本例中,它不会影响可点击性,因为……
我过去在输入框内使用标签时,是用
display: block;
、height: 0;
、overflow: hidden;
来隐藏标签的视觉效果……只使用占位符属性来显示视觉标签……您可以用伪选择器来设置占位符文本的样式……我的问题……这样做可以吗?或者从语义上来说这样做可以吗?我用这种方法的想法是屏幕阅读器仍然会读取标签……但对于有视觉障碍的用户来说它们会被隐藏……
Chris,你说得对,但我的意思是真正点击文本。比如,在文本的中间。在“姓氏”字段中输入一个姓名,然后尝试点击前几个字符之间。输入框将获得焦点,但光标将放在文本的末尾。很不友好 :)
关于点击进入文本的观点很棒!
似乎这样是最好的方法。
(更改与演示相关的选择器。)
我以前用过另一个技巧来避免点击标签而不是点击输入文本,就是将标签的 z-index 设置在字段下方,并为输入字段设置透明背景。
字段包装器可以恢复背景。
如果设计允许,我还喜欢在聚焦时将标签移动到可见区域,这样用户在输入时仍然可以看到标签。
或者更好的是,**始终使标签可见!** 特别是在使用自动填充时,我真的很喜欢检查所有字段是否都已正确自动填充。 这种技术很好,但在我看来,它只应该用于非常小的表单(例如搜索栏或登录),不会影响可用性。
我很好奇,即使将标签放在输入之后,并且for 和id 链接正确,所有屏幕阅读器是否都能正常工作。
这就是浮动标签模式非常有效的地方。
我希望我能回复回复,但,好吧。
我想补充一点:我同意@René所说的一切。
:placeholder-shown
很不错,我之前没听说过。在您输入电子邮件时,在有效和无效之间来回切换有点麻烦。 您可以执行以下操作
它实现了一些功能。
1. 只要有人快速输入,它就不会在无效和有效之间切换,这在您输入电子邮件地址时自然会发生两次。
2. 它不会影响非电子邮件字段(这种来回切换不应该在其他任何地方发生,并且立即反馈通常是更好的选择)。
3. 如果有人修复了无效的电子邮件,则不会有任何延迟,我认为这一点很重要。
我喜欢它。
这太聪明了! 就像 CSS 中的
debounce()
方法!喜欢 :placeholder-shown 技巧! 对于不支持的浏览器是否有任何 polyfill?
如果字段被选中,但没有输入任何内容会怎样? 不同的浏览器对占位符的处理方式不同。 有些浏览器在字段被选中时立即隐藏占位符。 其他浏览器则要等到开始输入时才隐藏。
在聚焦时隐藏占位符的情况下,它不一定能告诉您字段是否有值。 它只会告诉您占位符没有显示。 这可能是一个边缘情况,但完全有可能。 对吧?
很棒的文章! 我唯一犹豫的是在内容输入期间对电子邮件地址和密码的验证消息。 用户开始输入并看到红色错误,直到内容输入有效。 我在更多网站上看到这种情况,并且了解这是渐进式验证,不需要在提交尝试后重新访问。 当遇到这种情况时,我的 UX 感觉是
“我正在尝试输入有效的密码,希望它是一个符合要求的好的密码。 这需要集中注意力,而这条消息分散了我的注意力。”
“我不想在输入错误之前被告知我错了。”
我认为时机没有错,但我质疑反馈类型。 我更希望密码验证规则在输入之前就呈现。 我更喜欢用于姓名和姓氏的更抽象、在我看来不那么分散注意力的验证。 我认为标志性提示是更好的反馈,尽管我仍然不喜欢使用“X”图标。
我意识到这是一个 UX 问题,而不是 CSS 问题,但我还是想提出来。 :-)
@Eric Carlisle,
我一直很喜欢 MailChimp 对密码字段的处理方式,在最前面显示要求,并在满足要求时(在输入时)逐一标记,并在满足所有要求后给出确认。
https://login.mailchimp.com/signup
Firefox 有自定义伪选择器
-moz-ui-invalid
,它正是您想要用于无效的检测器,它只在第一次使用时在失焦或提交后显示无效状态,但在之后的每个字符上都会显示。https://mdn.org.cn/en/docs/Web/CSS/:-moz-ui-invalid
我还强烈建议使用Webshim 作为表单验证的 polyfill,它在使用原生 HTML5 标记的地方提供了 JS 备份,以及更多功能。
非常聪明! 一个负面影响是您无法(轻松地)使用鼠标选择您输入的电子邮件地址。
太棒了!
在我看来,在许多情况下不建议隐藏标签,因为这可能会影响可用性和可访问性。 在填写完此类表单后,很难记住哪个标签对应哪个字段。 对于“名字”或电子邮件地址来说,这可能很明显,但并不总是这样。 此外,由于相应的标签丢失,重新检查是否已正确填写所有字段很困难。
因此,我喜欢这种方法,标签仍然显示,但以不那么突兀的方式显示,就像这样
http://codepen.io/MattDiMu/pen/bepmEK
+1
这太酷了,谢谢大家。
首先,感谢您提供一篇很棒的文章。
我唯一的问题是如何使用 Selenium 或类似的自动化测试框架测试 required 属性? 我认为不可能获取消息的文本或检查消息是否已显示,因为据我了解,它在页面上没有任何单独的 html 标记。
要求 div 的初始状态为 max-height: 0,在无效输入+聚焦时为 max-height > 0。
这是可以测试的。
required 属性本身已经可以测试了,填充或删除所有其他字段,并进行脚本提交。
我必须承认,我对 selenium 的经验不多,可能还有更好的方法进行检查。
很棒的东西! 请记住,任何在客户端完成的验证都可以被禁用。 因此,除非您想冒着通过表单提交不正确或不安全数据的风险,否则验证也需要存在于后端。
这对于 UX 来说非常棒!
我仍然不明白为什么我们应该使用标签(作为占位符),而不是为此目的而设计的占位符?
占位符和标签的用途不同。
占位符旨在提示如何填写字段。 标签旨在描述应该填写什么。 此外,标签(除非像本文中一样被修改)在字段被填充后会保持可见。
例如:
<label>EAN<input type=text required name=postal placeholder='only digits like 013983'></label>
https://www.w3.org/WAI/GL/wiki/Using_@placeholder_on_input
谢谢,我理解标签的总体用途,但我仍然不明白为什么我们应该改变它们的根本用途(含义),并将它们用作占位符?
标签(据我了解)并非为此而设计,
相反,如您所说,它们应该描述应该输入到输入框中的内容,并且始终保持可见。
美观。
设计师想要占位符——程序员(和可访问性人员等)想要标签。
因此,作为折衷方案,我们让标签看起来像占位符。
就像一些评论已经提到的那样,可以这样做,但这并不意味着这是一个好的做法。
我完全同意你,尤其是这部分:“可以这样做,但这并不意味着这是一个好的做法。”。
但想想那些会阅读这篇文章的新手,其中 Chirs Coyier,他在 web 开发方面很有权威,
说:“……您可以使用占位符的视觉模式,但使用真实的标签。”
并没有提到任何关于最佳实践的信息。
我不确定我是否也漏掉了要点。 但我同意 Konstantin 的观点,为什么你使用标签作为占位符,而应该使用占位符属性呢?
我曾经有一个朋友给我讲了一个令人心碎的故事。
他当时正在为一所盲人高中做一些网页工作。他们做了很多研究,因为这是他们公司第一次做需要(显然)高水平可访问性的网页工作。在研究过程中,他们观看了很多孩子使用网页的情况。
其中一些孩子明年就要去上大学了,他们正在申请大学。大多数大学的申请都是在线进行的。网页表单!有些网页表单的结构非常糟糕,以至于孩子们根本无法理解这些字段应该填写什么信息。主要问题是:输入字段没有关联的标签(通过
for
和id
属性连接)。人们会主动提出帮忙,但这些孩子会愤怒地拒绝。他们要去上大学了,他们要独立生活了。而在他们旅程的第一步,他们就需要帮助,因为有些人构建的网站简直无法使用。
我在本文中要说明的是,你可以使用占位符视觉模式来显示真实的标签。正如我提到的,这在某些情况下非常有用,尤其是在表单空间非常有限或具有明显模式的情况下。可访问性不需要受到影响。我也同意那些认为标签应该始终可见(以及正确构建)的人。
目前,在视觉设计/样式计划中,如果
for
和id
属性连接可以很好地融入,那么直接用label
元素包裹input
元素,这种做法是否还被认为是可行的?这是我对这个问题的看法,我几乎100%同意Chris的观点,可能只有一点细微的差别。首先,无论是否使用占位符,都需要正确的标签。这在语义上是正确的,而且有利于可访问性。René在他关于“不同目的”的评论中说得最好。所以,这里实际上有两个问题:
我们应该使用占位符作为“标签”(省略真正的
<label>
元素)吗?我无法想象这样做有什么好的理由。我更喜欢在同一个项目中对所有表单使用相同的策略——我的意思是,一组 CSS 和 JS 来管理所有表单。因此,注册表单的策略与“编辑我的帐户”表单的策略相同。占位符不能替代标签的原因(除了可访问性问题之外)是,如果我访问一个已经填写数据的表单(例如“编辑我的帐户”),而且由于使用占位符作为标签,因此没有明显的方式知道字段的含义,这将是一个问题。我们应该使用标签并用 CSS 将其放置在占位符的位置吗?我理解Gavin的观点(为什么要重新发明轮子?),也理解Chris关于“我们始终需要标签,可访问性等”的观点。我的观点是,如果你要使用 CSS 将标签放置在占位符的位置,因为你“喜欢那种外观”,那么至少要使用“浮动标签”策略(http://bradfrost.com/blog/post/float-label-pattern/),这样在编辑模式下就不会出现问题,我可以看到我正在编辑的内容。
另外一个想法
这些都是非常好的例子,说明了 HTML 和 CSS 在你开始编写脚本之前就能提供多少价值。我唯一要吐槽的是,有关格式、密码有效性等的说明应该始终在用户开始输入之前显示,作为标签的一部分,或者至少在输入字段之前显示。给用户一个第一次就做对的机会!任何其他做法都是让他们猜测你的要求,然后在他们猜错时斥责他们。
http://codepen.io/Nice2MeatU/pen/pjEMZR
这是我对这个问题的看法
在这个 Pen 中,空字段被认为是无效的(当它们是必填项时)。
如果字段是必填项,则边框在获得焦点时变为蓝色,否则变为灰色。
我只需要进一步研究一下正则表达式。电子邮件验证在大多数浏览器中都可以正常工作,但并非所有浏览器都支持。而且这里还提到了对我的 CSS 和属性的支持问题。
另一个专业提示:就表单验证错误消息而言,
<label>
元素是“语义”的最佳候选者。标签与输入元素的比例是多对一。https://stackoverflow.com/questions/6014544/which-is-more-semantic-html-for-error-messages#6014665
感谢Chris提供的CodePen,我非常喜欢这种模式。
使用浮动标签怎么样?为了用户体验,我觉得始终保留标签是个好主意(尤其对于较长的表单)。
http://codepen.io/brentrobbins/pen/beexQR
真巧,Medium 上新发布了一篇关于表单输入占位符存在问题的文章
https://medium.com/simple-human/10-reasons-why-placeholders-are-problematic-f8079412b960#.n97i6ghsy
我不知道,浏览器电子邮件验证如此容易被欺骗
name@domain
足以满足我测试过的所有浏览器。
添加一个pattern属性会有所帮助
幸运的是,浏览器的要求不像你那样严格,否则我就无法注册几个有效的邮箱地址。第一个问题:有很多顶级域名长度超过3个字符。第二个问题:域名部分可以是类似IP地址的东西。第三个问题:域名甚至可以只有顶级域名或localhost。
我并不了解@符号之前的部分,但我猜想允许的字符会更多。
是的 René,这个正则表达式很糟糕,我只是从谷歌搜索结果中复制了第一个。但这不是我的重点。我认为从用户界面角度来看,当一个明显不正确的电子邮件地址通过检查标记验证时,会让人感到困惑。如果你对谷歌施加足够的压力,你就可以找到一个符合 RFC 5322 的正则表达式。或者——反过来——你可以使用比浏览器使用的正则表达式略好一些的东西(例如,要求有@符号和一个点)。
完整的正则表达式听起来不错,但它太重了。而且要求一个点仍然是不正确的。
维基百科给出了一个很好的注意事项列表:https://en.wikipedia.org/wiki/Email_address#Examples
超越编程角度
必填字段和类型转换只应该被视为对用户的提示,让他们填写字段。如果你想得更多,那就是自欺欺人。你可以使用客户端和服务器端验证尽你所能检查所有内容,但用户仍然可以使用虚假的邮箱地址进行错误操作。即使发送验证邮件也可以通过使用临时邮箱来欺骗。
因此,浏览器实现的功能是对用户而言的很好方法,让他们知道他们是否错误填写了某个字段。例如,在电子邮件字段中输入姓名。
你可能会说,更好的正则表达式可以帮助用户找到拼写错误,但我严重怀疑漏掉一个点比所有其他字母拼写错误加起来还要常见。至少在我们的数据库中不是这样。
如果我的帖子对你的帖子显得有些攻击性,请不要介意,它更多是针对一般情况的。我只是对这个问题有强烈的意见。这是由许多网站造成的,这些网站使用验证的方式非常错误。可能是因为程序员假设电子邮件地址始终是[email protected],或者每个国家/地区的邮政地址只包含街道名称和门牌号码。更不用说邮政编码了…
非常棒的文章,谢谢!虽然我理解情况并不容易,但这都是关于用户体验的。我们不能因为各种解决方案的组合而感到困扰和沮丧,因为这些解决方案肯定会导致积极的沟通解决方案的忽略。因此,许多不同的问题需要不同的解决方案。希望有更多类似的文章!
感谢你提供的维基百科链接!我之前不知道,name@domain 实际上是有效的地址。但我仍然认为,当我输入电子邮件地址的一半时弹出的检查标记并不好用,甚至会让人感到困惑。
在这种情况下,我认为用 JavaScript 替换浏览器的验证会更好,JavaScript 在 onBlur 事件发生时生效。或者使用 Alex Zaworski 的建议,设置一个1秒或更长的转换延迟。当我输入电子邮件地址到测试表单中时,我感到很困惑,这通常是一个提示,其他用户可能也会感到困惑。
我完全同意,许多表单中的电子邮件字段使用的是很糟糕的正则表达式。许多表单拒绝我经常使用的 + 地址,而且没有人希望总是禁用 JS 来填写一个验证不正确的表单。
嗯?当然有。只需执行
document.querySelector(":placeholder-shown");
。如果支持,它不会抛出SyntaxError
。在 Firefox、Edge 和 IE11 中测试过。
很喜欢,但我发现了一个问题,尽管我的表单使用了相同的结构,但标签不像这里的演示那样可点击。我看到的演示和我的设置之间唯一的样式差异是,我的标签有一个 `display` 属性(修改它不会影响行为)。
什么会影响像这样点击标签元素的结果?
与其使用似乎没有得到广泛支持的 `:placeholder-shown`,不如使用 Javascript 检测输入字段是否具有值?类似这样的方法应该可以解决问题(我使用的是 JQuery,因为我熟悉它,但它并非严格必要)
字段内的占位符文本是个坏主意。句号。
无论它们在语义上是标签还是占位符都无关紧要。它们存在很多问题,正如 Adam Silver 的文章(由 Brent 发布)所述。
令人担忧的是,知名人士 Chris Coyier 发布了这种技巧,可能会加剧这种糟糕的网络趋势。
这不是设计师与开发人员与无障碍性之间的斗争。**这是关于用户体验,对****所有人****。 除非你绝对必须这样做——这种情况很少发生——你永远不应该在字段中使用占位符文本。
Chris 所展示的的其他问题
内置的 HTML5 验证消息措辞和设计都很糟糕,应该像瘟疫一样避免
有时,唯一指示验证失败的是粉红色阴影,这是无法访问的。
我赞同其他评论者已经说过的内容:仅仅因为你可以做某事并不意味着你应该做。这使得我们社区中的领导者在提出建议时要更加谨慎变得至关重要。
我完全同意 Jessica 的所有观点。
看到开发人员和设计师将宝贵的时间浪费在这样一个糟糕的想法上,我感到非常难过。
请:我们还有很多其他需要你们去做的事情。例如,为什么不制作一个无障碍的类型提示框呢?
请记住:永远不要在字段中使用占位符文本。