我正在构建一个表单,想要使用:invalid
选择器,如果用户在提交时没有填写"必填"的输入字段,则给这些字段添加红色边框,但是使用这个选择器会导致在页面加载时就已经出现突出显示。在让用户至少填写一次之前,给他们这种警告似乎不太友好。
有没有办法只在尝试提交表单后突出显示这些字段,换句话说,是否有一种方法只在单击提交按钮(或至少失去焦点在必填输入字段上)后才运行验证?
<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');
});
非常简单,只需使用#ID:invalid:focus
仅在焦点集中时进行验证,而不是在页面加载时进行验证。
除了 @Alexander Farkas 的帖子外,Dave Rupert 在这里提供了一个非常实用的解决方案:更加愉悦的HTML5表单验证。
它的本质是向表单输入元素添加CSS类,在用户尝试提交表单后才显示。这样做可以获得更好的用户体验,因为这些元素不会默认展示无效的样式,或者当用户通过它们时也不会展示无效的样式,从而提高了可访问性。
在发现这个方案之前,我尝试使用:invalid:focus
和其他伪元素样式,但没有达到预期的效果。虽然我尽可能多地使用纯CSS进行样式设计,但这看起来像是效率优秀的JS的解决方案的应用场景。
没有现成的解决方案。
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)。
invalid
事件是从表单元素而不是document
触发的,请检查https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/invalid_event。 - tanguy_kinvalid
事件是由表单元素触发的,而不是document
,请查看https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/invalid_event。 - tanguy_k这里有另一个解决方案,仅在提交尝试后样式化输入。
<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>
.submit-attempt input:invalid, .submit-attempt select:invalid {
border: 1px solid red;
}
<style>
input:required:focus:invalid {
...
}
</style>
虽然这是一个老问题,但对于可能会发现它有用的人:我写了一个小脚本,在尝试提交表单时向表单添加一个类,以便您可以以不同的样式来设计已经尝试过提交和未尝试过提交的表单:
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;
}
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 novalidate>
。 - RajV:user-invalid
使用:user-invalid
(MDN),可以实现所需效果。与: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>
:invalid
伪类来为不支持JavaScript的用户提供样式,并为支持JS的用户覆盖它,使用真正的类。 - zzzzBov