表单验证 UX 在 HTML 和 CSS 中

Avatar of Chris Coyier
Chris Coyier

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 $200 免费赠送额度!

您只需使用 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 确保满足必填条件,但该选择器也有助于验证输入类型。

显示有关类型验证的提醒

您还可以要求输入的值为特定类型,例如 emailnumber这里有 所有类型的示例。

<input id="email" name="email" required="" type="email">

该输入既是必填项,也需要是有效的电子邮件地址格式。让我们为此做一些 UX 工作

  1. 当字段获得焦点时,告诉用户相关要求
  2. 提醒他们该字段没有有效的其他值

但是……当输入为空时,不要显示任何提醒。也就是说,不要假设无效状态。这有点烦人,而且不必要地消极。为了做到这一点,我们需要知道输入是否为空。

子技巧!测试输入是否有值

我们想用 :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;
    }

  }
}

您可以创建强大的验证

不仅仅是 requiredtype="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 之外。

更多