Html 延迟 HTML5 : 伪类无效,直到第一个事件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7920742/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Delay HTML5 :invalid pseudo-class until the first event
提问by kojiro
I recently discovered that the :invalid
pseudo-class applies to required
form elements as soon as the page loads. For example, if you have this code:
我最近发现:invalid
伪类required
在页面加载后立即应用于表单元素。例如,如果您有以下代码:
<style>
input:invalid { background-color: pink; color: white; }
input:valid { background-color: white; color: black; }
</style>
…
<input name="foo" required />
Then your page will load with an empty pink input element on it. Having validation built in to HTML5 is great, but I don't think most users expect the form to validate before they've had a chance to enter any values at all. Is there any way to delay the application of the pseudo-class until the first event affecting that element (form submit, blur, change, whatever's appropriate)? Is it possible to do this without JavaScript?
然后您的页面将加载一个空的粉红色输入元素。将验证内置到 HTML5 中很棒,但我认为大多数用户根本不希望表单在他们有机会输入任何值之前进行验证。有没有办法延迟伪类的应用,直到影响该元素的第一个事件(表单提交、模糊、更改,任何合适的)?没有 JavaScript 可以做到这一点吗?
采纳答案by Bart
http://www.alistapart.com/articles/forward-thinking-form-validation/
http://www.alistapart.com/articles/forward-thinking-form-validation/
Since we only want to denote that a field is invalid once it has focus, we use the focus pseudo-class to trigger the invalid styling. (Naturally, flagging all required fields as invalid from the start would be a poor design choice.)
由于我们只想表示一个字段一旦获得焦点就无效,因此我们使用焦点伪类来触发无效样式。(当然,从一开始就将所有必填字段标记为无效将是一个糟糕的设计选择。)
Following this logic, your code would look something like this...
按照这个逻辑,你的代码看起来像这样......
<style>
input:focus:required:invalid {background-color: pink; color: white;}
input:required:valid {background-color: white; color: black; }
<style>
Created a fiddle here: http://jsfiddle.net/tbERP/
在这里创建了一个小提琴:http: //jsfiddle.net/tbERP/
As you'd guess, and as you'll see from the fiddle, this technique only shows the validation styling when the element has focus. As soon as you move focus off, the styling is dropped, regardless of whether it is valid or not. Not ideal by any means.
正如您所猜测的那样,并且正如您将从小提琴中看到的那样,此技术仅在元素具有焦点时显示验证样式。一旦您将焦点移开,样式就会被删除,无论它是否有效。无论如何都不理想。
回答by kzh
This is not possible in pure CSS, but can be done with JavaScript. This is a jQuery example:
这在纯 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');
});
/**
* 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;
}
<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>
回答by Carl
These answers are out of date. Now you can do this by checking for a placeholder pseudo-class with CSS.
这些答案已经过时了。现在您可以通过使用 CSS 检查占位符伪类来完成此操作。
input:not(:placeholder-shown):invalid {
background-color: salmon;
}
form:invalid button {
background-color: salmon;
pointer-events: none;
}
<form>
<input type="email" placeholder="[email protected]" required>
<button type="submit">Submit</button>
</form>
It starts with a normal background and turns pink as you enter you incomplete email address into it.
它以正常背景开始,当您输入不完整的电子邮件地址时会变成粉红色。
回答by Aaron Benjamin
Mozilla takes care of this with their own :-moz-ui-invalidpseudoclass that only applies to forms after they've been interacted with. MDN does not recommend using this due to lack of support. However, you can modify it for Firefox.
Mozilla 使用他们自己的:-moz-ui-invalid伪类来处理这个问题,该伪类仅适用于与表单交互后的表单。由于缺乏支持,MDN 不建议使用它。但是,您可以为 Firefox 修改它。
There's a level 4 spec for a :user-invalidspec on the horizon that will offer similar behavior.
即将出现的:user-invalid规范有一个级别 4 规范,它将提供类似的行为。
Sorry if this doesn't help, but I hope it offers some context.
对不起,如果这没有帮助,但我希望它提供一些背景。
回答by aghouseh
I created a small shim to deal with this in my codebase. I just start off with my <form/>
element having the novalidate
property along with a data-validate-on="blur"
attribute. This watches for the first event of that type. This way you can still use the native :invalid
css selectors for the form styling.
我在我的代码库中创建了一个小垫片来处理这个问题。我刚开始时我的<form/>
元素具有novalidate
属性和data-validate-on="blur"
属性。这会监视该类型的第一个事件。通过这种方式,您仍然可以使用原生:invalid
css 选择器进行表单样式设置。
$(function () {
$('[data-validate-on]').each(function () {
var $form = $(this);
var event_name = $form.data('validate-on');
$form.one(event_name, ':input', function (event) {
$form.removeAttr('novalidate');
});
});
});
回答by Jonathan Calvin
While using HTML5 form validation, try to use the browser to detect for invalid submissions/fields, rather than re-inventing the wheel.
在使用 HTML5 表单验证时,尝试使用浏览器来检测无效的提交/字段,而不是重新发明轮子。
Listen for the invalid
event to add a class of 'invalid' to your form. With the 'invalid' class added, you can go to town with styling your form using CSS3 :pseudo
selectors.
侦听invalid
事件以将“无效”类添加到您的表单。添加“无效”类后,您可以使用 CSS3:pseudo
选择器为表单设置样式。
For example:
例如:
// where myformid is the ID of your form
var myForm = document.forms.myformid;
var checkCustomValidity = function(field, msg) {
if('setCustomValidity' in field) {
field.setCustomValidity(msg);
} else {
field.validationMessage = msg;
}
};
var validateForm = function() {
// here, we're testing the field with an ID of 'name'
checkCustomValidity(myForm.name, '');
if(myForm.name.value.length < 4) {
checkCustomValidity(
// alerts fields error message response
myForm.name, 'Please enter a valid Full Name, here.'
);
}
};
/* here, we are handling your question above, by adding an invalid
class to the form if it returns invalid. Below, you'll notice
our attached listener for a form state of invalid */
var styleInvalidForm = function() {
myForm.className = myForm.className += ' invalid';
}
myForm.addEventListener('input', validateForm, false);
myForm.addEventListener('keyup', validateForm, false);
myForm.addEventListener('invalid', styleInvalidForm, true);
Now, simply style your form as you see fit based on the 'invalid' class we've attached.
现在,只需根据我们附加的“无效”类设置您认为合适的表单样式。
For example:
例如:
form.invalid input:invalid,
form.invalid textarea:invalid {
background: rgba(255, 0, 0, .05);
border-color: #ff6d6d;
-webkit-box-shadow: 0 0 6px rgba(255, 0, 0, .35);
box-shadow: 0 0 6px rgba(255, 0, 0, .35);
}
回答by Liquinaut
There is a html5 invalid
event that fires on form elements before the submit
event occurs for each element that does not pass checkValidity. You can use this event to apply a class for example to the surrounding form and display :invalid styles only after this event occurs.
对于未通过 checkValidity 的每个元素,invalid
在submit
事件发生之前,会在表单元素上触发html5事件。您可以使用此事件将类应用于例如周围的表单并仅在此事件发生后显示 :invalid 样式。
$("form input, form select, form textarea").on("invalid", function() {
$(this).closest('form').addClass('invalid');
});
Your CSS would then look something like this:
您的 CSS 将如下所示:
:invalid { box-shadow: none; }
.invalid input:invalid,
.invalid textarea:invalid,
.invalid select:invalid { border: 1px solid #A90909 !important; background-color: #EEC2C2; }
The first line removes the default styling, so form elements look neutral at page load. As soon as the invalid event fires (when a user tries to submit the form), the elements are visibly rendered invalid.
第一行删除了默认样式,因此表单元素在页面加载时看起来是中性的。一旦无效事件触发(当用户尝试提交表单时),元素就会明显地呈现为无效。
回答by yunzen
This is a VanillaJS (no jQuery) version of kzh's answer
这是一个VanillaJS(无jQuery的)的版本KZH的答案
{
let f = function() {
this.classList.add('touched')
}
document
.querySelectorAll('input')
.forEach((e) => {
e.addEventListener('blur', f, false)
e.addEventListener('keydown', f, false)
})
}
/**
* 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;
}
<p><label>
Name:
<input type="text" required> *required
</label></p>
<p><label>Age:
<input type="text">
</label></p>
回答by robrecord
Following on from agouseh's idea, you can have a bit of javascript to tell when the submit button has been focussed, and have validation show up at that time.
继agouseh的想法之后,您可以使用一些 javascript 来判断提交按钮何时被聚焦,并在那时显示验证。
The javascript will add a class (eg. submit-focussed
) to the form field when the submit button is focussed or clicked, which then allows the CSS to style invalid inputs.
submit-focussed
当提交按钮被聚焦或点击时,javascript 将向表单字段添加一个类(例如),然后允许 CSS 设置无效输入的样式。
This follows the best practice of showing validation feedback after the user has finished filling in the fields, as according to research there is no additional benefit to showing it during the process.
这遵循在用户完成填写字段后显示验证反馈的最佳实践,因为根据研究,在此过程中显示它没有额外的好处。
document
.querySelector('input[type=submit]')
.onfocus = function() {
this
.closest('form')
.classList
.add('submit-focussed');
};
form.submit-focussed input:invalid {
border: thin solid red;
}
<form>
<label>Email <input type="email" required="" /></label>
<input type="submit" />
</form>
jQuery alternative
jQuery 替代品
(function($) {
$('input[type=submit]').on('focus', function() {
$(this)
.parent('form')
.addClass('submit-focussed');
});
})(jQuery); /* WordPress compatible */
回答by cHao
You could make it so that only elements that have a certain class on them andare required, are pink. Add an event handler to each required element that adds that class when you leave the element.
您可以将其设置为只有具有特定类并且是必需的元素是粉红色的。向每个必需元素添加一个事件处理程序,以便在您离开元素时添加该类。
Something like:
就像是:
<style>
input.touched:invalid { background-color: pink; color: white; }
input.touched:valid { background-color: white; color: black; }
</style>
<script>
document.addEventListener('DOMContentLoaded', function() {
var required = document.querySelectorAll('input:required');
for (var i = 0; i < required.length; ++i) {
(function(elem) {
function removeClass(name) {
if (elem.classList) elem.classList.remove(name);
else
elem.className = elem.className.replace(
RegExp('(^|\s)\s*' + name + '(?:\s+|$)'),
function (match, leading) {return leading;}
);
}
function addClass(name) {
removeClass(name);
if (elem.classList) elem.classList.add(name);
else elem.className += ' ' + name;
}
// If you require a class, and you use JS to add it, you end up
// not showing pink at all if JS is disabled.
// One workaround is to have the class on all your elements anyway,
// and remove it when you set up proper validation.
// The main problem with that is that without JS, you see what you're
// already seeing, and stuff looks hideous.
// Unfortunately, you kinda have to pick one or the other.
// Let non-blank elements stay "touched", if they are already,
// so other stuff can make the element :invalid if need be
if (elem.value == '') addClass('touched');
elem.addEventListener('blur', function() {
addClass('touched');
});
// Oh, and when the form submits, they need to know about everything
if (elem.form) {
elem.form.addEventListener('submit', function() {
addClass('touched');
});
};
})(required[i]);
}
});
</script>
And of course, it won't work as is in IE8 or below, as (a) DOMContentLoaded
is relatively new and wasn't standard when IE8 came out, (b) IE8 uses attachEvent
rather than the DOM-standard addEventListener
, and (c) IE8 isn't going to care about :required
anyway, as it doesn't technically support HTML 5.
当然,它不会像在 IE8 或更低版本中那样工作,因为 (a)DOMContentLoaded
是相对较新的并且在 IE8 出现时不是标准的,(b) IE8 使用attachEvent
而不是 DOM 标准addEventListener
,以及 (c) IE8:required
无论如何都不会关心,因为它在技术上不支持 HTML 5。