延迟HTML5:第一个事件之前的伪类无效

koj*_*iro 61 validation usability html5

我最近发现:invalid伪类required在页面加载时立即应用于表单元素.例如,如果您有此代码:

<style>
input:invalid { background-color: pink; color: white; }
input:valid { background-color: white; color: black; }
</style>
…
<input name="foo" required />
Run Code Online (Sandbox Code Playgroud)

然后你的页面将加载一个空的粉红色输入元素.对HTML5内置验证非常好,但我认为大多数用户都不希望表单在有机会输入任何值之前进行验证.有没有办法延迟伪类的应用,直到影响该元素的第一个事件(表单提交,模糊,更改,任何适当的)?没有JavaScript可以做到这一点吗?

Bar*_*art 36

http://www.alistapart.com/articles/forward-thinking-form-validation/

由于我们只想表示一个字段有焦点后无效,我们使用焦点伪类来触发无效样式.(当然,从一开始就将所有必填字段标记为无效将是一个糟糕的设计选择.)

遵循这个逻辑,你的代码看起来像这样......

<style>
    input:focus:required:invalid {background-color: pink; color: white;}
    input:required:valid {background-color: white; color: black; }
<style>
Run Code Online (Sandbox Code Playgroud)

在这里创造了一个小提琴:http://jsfiddle.net/tbERP/

正如您所猜测的那样,正如您从小提琴中看到的那样,此技术仅在元素具有焦点时显示验证样式.只要关闭焦点,样式就会被删除,无论它是否有效.无论如何都不理想.

  • "无论如何都不理想." 确实.在元素失去焦点后,是否有一种方法可以将样式应用于有效但不需要的内容?我还没有想出办法. (15认同)

kzh*_*kzh 21

这在纯CSS中是不可能的,但可以使用JavaScript完成.这是一个jQuery示例:

// use $.fn.one here to fire the event only once.
$(':required').one('blur keydown', function() {
  console.log('touched', this);
  $(this).addClass('touched');
});
Run Code Online (Sandbox Code Playgroud)
/**
 * All required inputs initially are yellow.
 */
:required {
  background-color: lightyellow;
}

/**
 * If a required input has been touched and is valid, it should be white.
 */
.touched:required:valid {
  background-color: white;
}

/**
 * If a required input has been touched and is invalid, it should be pink.
 */
.touched:required:invalid {
  background-color: pink;
}
Run Code Online (Sandbox Code Playgroud)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>
  <label>
    Name:
    <input type="text" required> *required
  </label>
</p>
<p>
  <label>Age:
    <input type="text">
  </label>
</p>
Run Code Online (Sandbox Code Playgroud)

  • 这是我更喜欢的解决方案,但您不再需要 jQuery。这可以通过简单的 Javascript 来完成。 (2认同)

Car*_*arl 20

这些答案已过时.现在,您可以通过使用CSS检查占位符伪类来完成此操作.

input:not(:placeholder-shown):invalid {
    background-color: salmon;
}
form:invalid button {
    background-color: salmon;
    pointer-events: none;
}
Run Code Online (Sandbox Code Playgroud)
<form>
    <input type="email" placeholder="me@example.com" required>
    <button type="submit">Submit</button>
</form>
Run Code Online (Sandbox Code Playgroud)

它以正常背景开始,并在您输入不完整的电子邮件地址时变为粉红色.

  • 不幸的是,当您需要通过唯一验证时,它不起作用。当您触摸必填字段或尝试提交包含必填字段的表单时,它应该显示错误。空的必填字段仍将显示占位符。 (6认同)
  • 值得注意的是,如果您关心IE或Edge支持,则根本不支持`:placeholder-shown`伪类.https://caniuse.com/#feat=css-placeholder-shown (4认同)

Aar*_*min 5

Mozilla 用它自己的伪类来处理这个问题,:-moz-ui-invalid该伪类仅适用于与表单交互后的表单。由于缺乏支持,MDN 不建议使用此方法。但是,您可以针对 Firefox 进行修改。

即将推出的 4 级规范:user-invalid将提供类似的行为。


yun*_*zen 5

这是kzh答案VanillaJS(无 jQuery)版本

{
  let f = function() {
    this.classList.add('touched')
  }
  document
    .querySelectorAll('input')
    .forEach((e) => {
      e.addEventListener('blur', f, false)
      e.addEventListener('keydown', f, false)
    })
}
Run Code Online (Sandbox Code Playgroud)
/**
 * All required inputs initially are yellow.
 */
:required {
  background-color: lightyellow;
}

/**
 * If a required input has been touched and is valid, it should be white.
 */
.touched:required:valid {
  background-color: white;
}

/**
 * If a required input has been touched and is invalid, it should be pink.
 */
.touched:required:invalid {
  background-color: pink;
}
Run Code Online (Sandbox Code Playgroud)
<p><label>
  Name:
  <input type="text" required> *required
</label></p>
<p><label>Age:
  <input type="text">
</label></p>
Run Code Online (Sandbox Code Playgroud)

  • 虽然这是一个很好的解决方案,但您可能需要将 `querySelectorAll` 替换为 `getElementsByTagName`,因为它在我的机器上大约快 17000 倍(!)。自己测试一下:https://jsperf.com/queryselectorall-vs-getelementsbytagname (2认同)