HTML5中的验证:提交后的:invalid类

32

我正在构建一个表单,想要使用:invalid选择器,如果用户在提交时没有填写"必填"的输入字段,则给这些字段添加红色边框,但是使用这个选择器会导致在页面加载时就已经出现突出显示。在让用户至少填写一次之前,给他们这种警告似乎不太友好。

有没有办法只在尝试提交表单后突出显示这些字段,换句话说,是否有一种方法只在单击提交按钮(或至少失去焦点在必填输入字段上)后才运行验证?


使用:invalid伪类来为不支持JavaScript的用户提供样式,并为支持JS的用户覆盖它,使用真正的类。 - zzzzBov
15个回答

10
我曾用这种方法在我的项目中,所以无效的字段只会在提交后被突出显示:
HTML:
<form>
  <input type="email" required placeholder="Email Address">
  <input type="password" required placeholder="Password">
  <input type="submit" value="Sign in">
</form>

CSS:

input.required:invalid {
    color: red;
}

JS(jQuery):

$('[type="submit"]').on('click', function () {
    // this adds 'required' class to all the required inputs under the same <form> as the submit button
    $(this)
        .closest('form')
        .find('[required]')
        .addClass('required');
});

9

非常简单,只需使用#ID:invalid:focus

仅在焦点集中时进行验证,而不是在页面加载时进行验证。


2
这样做不会在提交时为用户突出显示任何被忽略的字段或复选框。 - retrovertigo
2
@retrovertigo 不确定您使用的是哪个浏览器,但在最新版本的Firefox中,如果复选框是必需的且用户单击提交,则会将其聚焦。 - AmazingTurtle
啊,原来是这样 https://jsfiddle.net/scheinercc/o2yj5en3/5/ ... 我一定是误解了什么。 - retrovertigo

7

除了 @Alexander Farkas 的帖子外,Dave Rupert 在这里提供了一个非常实用的解决方案:更加愉悦的HTML5表单验证

它的本质是向表单输入元素添加CSS类,在用户尝试提交表单后才显示。这样做可以获得更好的用户体验,因为这些元素不会默认展示无效的样式,或者当用户通过它们时也不会展示无效的样式,从而提高了可访问性。

在发现这个方案之前,我尝试使用:invalid:focus和其他伪元素样式,但没有达到预期的效果。虽然我尽可能多地使用纯CSS进行样式设计,但这看起来像是效率优秀的JS的解决方案的应用场景。


5

没有现成的解决方案。

Mozilla有自己的伪类,用于处理非常相似的情况,称为“:-moz-ui-invalid”。如果你想实现类似的效果,你需要使用约束验证DOM-API:

if(document.addEventListener){
    document.addEventListener('invalid', function(e){
        e.target.className += ' invalid';
    }, true);
}

您还可以使用webshims lib polyfill,它不仅可以为不支持的浏览器提供polyfill,还会向所有浏览器添加类似于-moz-ui-invalid的内容(.form-ui-invalid)。


哦,好吧,如果你没有什么可以做的,那我可能要做JS验证:P 但是这很糟糕:P - Enrique Moreno Tent
1
@alexander farkas 用户输入信息到字段后,标记仍然存在。我该如何删除className,比如说onBlur? - JonSnow
这是行不通的:invalid事件是从表单元素而不是document触发的,请检查https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/invalid_event。 - tanguy_k
这是行不通的:invalid事件是由表单元素触发的,而不是document,请查看https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/invalid_event。 - tanguy_k

3
另一种方法是在加载JavaScript时,将“hide-hints”类添加到输入框中。当用户修改字段时,您可以删除该类。
然后,在CSS中,您可以将样式应用于“input:not(.hide-hints):invalid”。这意味着错误样式也会显示给没有JavaScript的用户。

这不会在提交时为用户突出显示任何被忽略的字段或复选框。 - retrovertigo

2

这里有另一个解决方案,仅在提交尝试后样式化输入。

HTML

<form id="sign-up-form" method="post" enctype="multipart/form-data" class="login-form sign-in-form">
    <input type="text" placeholder="Name" id="full-name" name="full-name" required>
    ...
</form>
<script>
    (() => {
        const form = document.getElementById('sign-up-form');
        form.noValidate = true;

        form.onsubmit = function(e) {
            e.preventDefault();
            this.reportValidity();

            if (this.checkValidity()) return this.submit();

            this.classList.add('submit-attempt')
        }
    })()
</script>

CSS

.submit-attempt input:invalid, .submit-attempt select:invalid {
    border: 1px solid red;
}

2

1
这个答案真的真的很好用。而且全部都是CSS! - undefined

1

虽然这是一个老问题,但对于可能会发现它有用的人:我写了一个小脚本,在尝试提交表单时向表单添加一个类,以便您可以以不同的样式来设计已经尝试过提交和未尝试过提交的表单:

window.addEventListener('load', function() {

    /**
     * Adds a class `_submit-attempted` to a form when it's attempted to be
     * submitted.
     *
     * This allows us to style invalid form fields differently for forms that
     * have and haven't been attemted to submit.
     */
    function addFormSubmitAttemptedTriggers() {

        var formEls = document.querySelectorAll('form');

        for (var i = 0; i < formEls.length; i++) {

            function addSubmitAttemptedTrigger(formEl) {

                var submitButtonEl = formEl.querySelector('input[type=submit]');

                if (submitButtonEl) {
                    submitButtonEl.addEventListener('click', function() {
                        formEl.classList.add('_submit-attempted');
                    });
                }

            }

            addSubmitAttemptedTrigger(formEls[i]);

        }

    }

    addFormSubmitAttemptedTriggers();

});

现在,尝试提交的表单将获得一个类名为_submit-attempted,因此您只能给这些字段添加红色框阴影:
input {
    box-shadow: none;
}

form._submit-attempted input {
    box-shadow: 0 0 5px #F00;
}

1
form.invalid {
  *:invalid {
    box-shadow: 0px 0px 2px 1px red;
  }
}

let form = document.querySelectorAll('form')[0]
form.addEventListener('submit', function() {
  if (!form.checkValidity()) {
    form.classList.add('invalid')
  }
})

通过上述的样式和JavaScript,表单控件只会在 submit 事件和 checkValidity 检查失败后显示 :invalid 样式。如果检查无效,则会将 invalid 类添加到表单并激活样式,否则表单将像往常一样提交。


如果<form>中的任何输入无效,则在提交表单时将不会调用“submit”事件处理程序。为使此方法起作用,您需要使用<form novalidate> - RajV

1

:user-invalid

使用:user-invalidMDN),可以实现所需效果。与:invalid不同的是,它仅在用户与元素交互或提交表单后激活。

目前,:user-invalid只支持Firefox和Safari浏览器,不支持Chrome和Edge浏览器。

#i1:invalid {
  outline: 3px red solid;
}

#i2:user-invalid {
  outline: 3px red solid;
}
<form>
  <div>
    <label>
      Required field (using <code>:invalid</code>):<br>
      <input required name="i1" id="i1">
    </label>
  </div>
  
  <br>
  
  <div>
    <label>
      Required field (using <code>:user-invalid</code>):<br>
      <input required name="i2" id="i2">
    </label>
  </div>
  
  <br>
  
  <button type="submit">Submit</button>
</form>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接