2011-10-27 70 views
42

我最近發現:invalid僞類適用於required表單元素一旦頁面加載。例如,如果您有以下代碼:延遲HTML5:無效的僞類直到第一個事件

<style> 
input:invalid { background-color: pink; color: white; } 
input:valid { background-color: white; color: black; } 
</style> 
… 
<input name="foo" required /> 

然後,您的頁面將加載一個空的粉紅色輸入元素。對HTML5進行驗證非常有用,但我認爲大多數用戶並不希望表單在他們有機會輸入任何值之前進行驗證。是否有任何方法可以延遲僞類的應用,直到影響該元素的第一個事件(表單提交,模糊,更改,適合的任何內容)爲止?沒有JavaScript可以做到這一點?

回答

27

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> 

創建這裏提供了一個小提琴:http://jsfiddle.net/tbERP/

正如你所猜測的,正如你從小提琴中看到的那樣,這種技術只在元素具有焦點時顯示驗證樣式。只要您將焦點移開,樣式將會丟失,無論其是否有效。不以任何方式理想。

+10

「不以任何方式理想。」確實。有沒有一種方法可以在元素失去焦點後將樣式應用於有效的元素,而不是必需的內容?我還沒有找到一個這樣做的方法。 –

+0

我可以想象一個(不存在的)pseduo類,用於像「提交」這樣的表單,以便它可以作爲任何包含輸入的父選擇器,如'#myform:submitted input:required:invalid'。因爲儘管目前這種情況確實是不直觀的,但期望CSS在特定情況下知道某個字段是無效的(爲什麼它不應該馬上這樣做,就其所知而言)並不現實?你真的想把輸入樣式與表單的狀態聯繫起來,而不是輸入本身(例如,當必填字段爲空並且提交父表單時)。 – Anthony

+0

這個答案:https:// stackoverflow。com/questions/41619497/how-to-make-pseudo-class-invalid-apply-to-an-input-after-submit-a-form實際上處理這個問題,我想即使它需要一點javascript 。它只是添加一個「提交」到表單的類(就像我建議的那樣),以便樣式規則可以是'form.submitted input:required:invalid' – Anthony

1

你可以這樣做,只有那些有一定類的元素是必需的,是粉紅色的。向離開元素時添加該類的每個必需元素添加一個事件處理程序。

喜歡的東西:

<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> 

當然,它不會工作,因爲在IE8或以下,如(一)DOMContentLoaded是比較新的,並沒有標準的時候IE8出來了,(B )IE8使用attachEvent而不是DOM標準addEventListener,以及(c)IE8是不會在乎:required無論如何,因爲它不技術上支持HTML 5

17

這是不可能的純CSS,但可以用JavaScript來完成。這是一個jQuery example

// 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>

+0

這是一個簡單的解決方案;) – fegemo

+0

這是我更喜歡的解決方案,但您不再需要jQuery。這可以用簡單的Javascript完成。 – micah

2

在使用HTML5表單驗證,嘗試使用瀏覽器來檢測無效的意見/場,而不是重新發明輪子。

收聽invalid事件,向您的表單中添加一個「invalid」類。隨着「無效」課程的添加,您可以使用CSS3 :pseudo選擇器爲您的表單造型。

例如:

// 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); 

現在,簡單的風格你的形式,你看我們根據附「無效」類適合。

例如:

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); 
} 
+1

呃,難道這不是重新發明輪子嗎? – Ryan

+0

重新發明車輪?這是輪...以上是處理HTML5表單驗證樣式,同時配對CSS和JS來解決他遇到的問題的有效方法。這允許他設置他的無效表單元素並避免頁面加載時的僞造風格。糾正我,如果我錯了,但我會說它是一個可靠的方法來解決他的問題。 –

2

存在對錶單元素觸發之前的submit事件未通過checkValidity每個元素出現HTML5 invalid事件。例如,您可以使用此事件將類應用於周圍的表單並僅在發生此事件後才顯示:無效的樣式。然後

$("form input, form select, form textarea").on("invalid", function() { 
    $(this).closest('form').addClass('invalid'); 
}); 

你的CSS會是這個樣子:

:invalid { box-shadow: none; } 
.invalid input:invalid, 
.invalid textarea:invalid, 
.invalid select:invalid { border: 1px solid #A90909 !important; background-color: #EEC2C2; } 

第一行刪除默認樣式,所以形成元素,在頁面加載看起來中性。只要無效事件觸發(用戶嘗試提交表單時),元素就會被視爲無效。

1

我在我的代碼庫中創建了一個小墊片來處理這個問題。我剛從我的<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'); 
     }); 
    }); 
}); 
0

的一個好方法是抽象:invalid, :valid用CSS類,然後一些JavaScript來檢查,如果輸入字段集中與否。

CSS:

input.dirty:invalid{ color: red; } 
input.dirty:valid{ color: green; } 

JS:

// Function to add class to target element 
function makeDirty(e){ 
    e.target.classList.toggle('dirty'); 
} 

// get form inputs 
var inputs = document.forms[0].elements; 

// bind events to all inputs 
for(let input of inputs){ 
    input.addEventListener('invalid', makeDirty); 
    input.addEventListener('blur', makeDirty); 
    input.addEventListener('valid', makeDirty); 
} 

DEMO

1

這些答案都過時了。現在你可以通過檢查一個帶CSS的佔位符僞類來做到這一點。

input:not(:placeholder-shown):invalid { 
 
    background-color: salmon; 
 
}
<form> 
 
    <input type="email" placeholder="[email protected]" required> 
 
</form>

它以一個正常的背景,當你輸入你不完整的電子郵件地址,它變成粉紅色。