Comprehensive HTML5 Form Validation Example
by Ford Heacock
HTML
<script src="http://modernizr.com/downloads/modernizr.js"></script>
<form>
<div>
<label for="title">Title:</label>
<select id="gender" autofocus>
<option selected></option>
<option>Mr.</option>
<option>Mrs.</option>
<option>Ms.</option>
<option>Dr.</option>
</select>
</div>
<div>
<label for="fullName">Name:</label>
<input id="fullName" title="Please provide your full name." x-moz-errormessage="Please provide your full name." required pattern="[a-zA-Z]*" />
</div>
<div>
<label>Gender:</label>
<label for="genderM">Male:</label>
<input type="radio" name="gender" id="genderM" title="Please provide your gender." required />
<label for="genderF">Female:</label>
<input type="radio" name="gender" id="genderF" required />
</div>
<div>
<label for="age">Age:</label>
<input type="number" id="age" step="1" min="16" max="120" title="Please provide your age." required />
</div>
<div>
<label for="appointment">Appointment Date:</label>
<input type="date" id="appointment" title="Please let us know the date on which you have an appointment." required />
</div>
<div>
<label for="telephone">Phone Number:</label>
<input type="tel" id="telephone" />
</div>
<div>
<label for="email">Email:</label>
<input type="email" id="email" title="Please provide us with a valid email address so we can contact you and verify your signup." required />
</div>
<div>
<label for="satisfaction">Satisfaction with the Product (1 worst - 10 best):</label>
<input type="range" id="satisfaction" min="1" max="10" step="1" value="5" />
<output id="satisfactionOutput">5</output>
</div>
<div>
<label for="comments">Comments:</label>
<textarea id="comments"></textarea>
...
CSS
form {
width: 500px;
overflow: hidden;
}
div {
padding: 10px 0;
}
label {
display: inline-block;
width: 200px;
font-weight: bold;
margin: 0 10px 0 0;
text-align: right;
}
label[for=genderM], label[for=genderF] {
font-weight: normal;
width: auto;
}
input[type=radio] {
margin-right: 20px;
}
input[type=submit] {
float: right;
}
textarea { vertical-align: middle; }
.submitted :invalid {
border: 1px solid red;
}
.submitted input[type=checkbox]:invalid, .submitted input[type=radio]:invalid {
border: none;
outline: 1px solid red;
}
.required label:after {
content: '*';
color: red;
}
.required label[for=genderM]::after, .required label[for=genderF]::after {
content: '';
}
output { display: none; }
input[type=range] + output {
padding-left: 10px;
}
::-webkit-validation-bubble {}
::-webkit-validation-bubble-message {}
::-webkit-validation-bubble-arrow {}
::-webkit-validation-bubble-arrow-clipper {}
/*
<div -webkit-validation-bubble>
<div -webkit-validation-bubble-arrow></div>
<div -webkit-validation-bubble-arrow-clipper></div>
<div -webkit-validation-bubble-message>Error Message</div>
</div>
*/
JavaScript
(function() {
//IE <= 8
if ((!window.addEventListener) || (!document.querySelectorAll)) return;
var requiredFields = document.querySelectorAll('[required]');
var parent;
for (var i = 0; i < requiredFields.length; i++) {
parent = requiredFields[i].parentNode;
//http://caniuse.com/classlist
if (parent.classList) {
parent.classList.add('required');
}
}
var input = document.createElement('input');
input.setAttribute('type', 'range');
var rangeTypeSupport = (input.type != 'text');
if (rangeTypeSupport) {
var satisfaction = document.getElementById('satisfaction');
var satisfactionOutput = document.getElementById('satisfactionOutput');
satisfactionOutput.style.display = 'inline';
satisfaction.addEventListener('change', function(event) {
satisfactionOutput.value = event.target.value;
});
}
var submitButton = document.getElementById('submitButton');
submitButton.addEventListener('click', function() {
var form = document.getElementsByTagName('form')[0];
//http://caniuse.com/classlist
if (form.classList) {
form.classList.add('submitted');
}
});
}());