For a list of form elements, refer to the MDN document. Making Forms Fabulous with HTML5 is another good article that talks specifically about HTML5 form elements.
Forms and their child elements should not use input names or ids that conflict with properties of a form, such as submit
, length
, or method
. Name conflicts can cause confusing failures. For a complete list of rules and to check your markup for these problems, see DOMLint. So, do not do this: <input type="submit" name="submit" id="submit">
A new (gaining usage in 2015) spec for displaying custom elements in a browser could be a great way to display some of the more complicated input elements such as <input type="color"> and <input type="date">. Learn more on the Web Components website. Some pre-built components can be found on the https://customelements.io/ website.
Several of the input types allow for a pattern attribute. You use it to specify a Javascript RegEx for validation. For example, to ensure a valid URL is entered, you can do this:
<input id="url2" type="url" placeholder="http://www.domain.com"
pattern="(http|https|ftp)\:\/\/[a-zA-Z0-9\-\.\/]*">
HTML5 introduced default validation for some elements. The brower will apply pseudo-classes for valid and invalid elements. So, you can highlight invalid elements in red, and good ones in green (for example).
The required and optional pseudo-classes are applied to form elements based on whether or not the required
attribute is present. You can then apply styling to those fields. For example:
input:required { font-size:2em; } input:optional { font-style:italic; background-color:inherit; } <p><label>Full name: <input type="text" size="12" required></label></p> <p><label>Weight: <input type="text" size="4"></label></p>
By default, Safari will use its own styling that you can’t override, unless you turn off the default styling. For example, if you want to specify the width and height of checkboxes then use the CSS property:
-webkit-appearance: none;
Setting the tabindex
attribute to -1
will remove the control from the tabbing order, but you can still set the focus using JavaScript (element.focus()
). Setting it to 0 will use the document order for tabbing, a -1 will not allow tabbing into the element.
You can group related form controls together with the fieldset element. Common examples are to group a list of radio button together. For example:
<fieldset> <legend>Choose your gift</legend> <label><input type="radio" name="car">Ferrari Enzo</label><br> <label><input type="radio" name="car">Lamborghini Gallardo</label><br> <label><input type="radio" name="car">Nissan GT-R</label><br> <label><input type="radio" name="car">Acura NSX</label><br> <label><input type="radio" name="car">McLaren P1</label><br> <label><input type="radio" name="car">Audi R8</label><br> <label><input type="radio" name="car">Pagani Zonda</label><br> <label><input type="radio" name="car">Audi R8</label> </fieldset>
If you have trouble styling the fieldset (say when using border-radius or box-shadow) try floating the fieldset.
By default, radio buttons have horrible alignment when the label text is long enought that it must wrap onto the second line.
Default behavior | Fixed |
---|---|
Unfortunately, you will have to structure your HTML (it will still be valid markup) is a specific manner. Namely, the <label>
tag must wrap the <input>
element vs. using the for
attribute.
/* Assumes you are putting your list inside a <fieldset> */ fieldset label { display: block; margin-left: 30px; } fieldset input { float:left; margin-left: -30px; } <fieldset> <legend>My List</legend> <label><input type="checkbox" name="chk" value="0"> This is a rather long label that will demonstrate how this looks when wrapped.</label> <label><input type="checkbox" name="chk" value="1"> Again, some dummy text because I can’t think of anythink clever to say right now.</label> </fieldset>
The astute reader may wonder why I didn’t just use text-indent: -30px; margin-left: 30px;
instead. Well, I wasn’t able to get it to work cross-browser and it would be a few pixels off. If anyone can get text-indent
to work, I would love to hear about it.
This element is used to store the output of a calculation. It formally defines a relationship between the fields used to get the data required to perform the calculation and an element to be used to display the results. It is also understood as a live region by some assistive technologies (which means that when the content of the <output>
element changes, the assistive technology is aware of that change and can react to it).
In this example the text to the right of the slider is displayed inside an output element.
<p><label for=size>Size: </label> <input type="range" id="size" min="5" max="50" value="20"> <output id="sizeVal" for="size">20</output> </p> <script> document.getElementById('size').addEventListener("change", function() { document.getElementById('sizeVal').innerHTML = this.value; }, false); </script>
There are times when you want all the text to be selected in a textfield (<input type="text">
) after you click it, or after validation. The best way to do that is fire the focus() and select() methods - in that order. For example:
$('#myTextBox').on('click',function() { this.focus(); this.select(); });
You must work with each individual button to determine anything about a Radio button group. You either need to loop over them (using straight Javascript), or select just the checked item (using jQuery).
The jQuery method is: $('input:radio[name="playAs"]:checked').val();
The form will only send one name/value pair to the server. e.g. playAs = $_POST['playAs']; //EXPRT
A checkbox is created with <input type="checkbox">
.
When you need to determine (through JavaScript) whether or not it has been checked, you must look at the checked property, not the checked attribute. The attribute is used to set the initial value when the page loads.
Right way (jQuery):
$('input:checkbox').each(function(){ if ($(this)[0].checked) { //the current checkbox has been checked } // OR // if ($(this).is(:checked)) { //the current checkbox has been checked } });
Right way (straight JavaScript):
var chkboxes = document.form1.myCheckboxes; for (var i=0; i<chkboxes.length; i++) { if (chkboxes[i].checked) { //the current checkbox has been checked } }
Wrong way:
$('input:checkbox:checked').each(function(){ //each instance has the attribute checked, but not //necessarily has been checked by the user. });
Note: Dynamically setting the attribute, will change the property.
If you have several related checkboxes, give them a name attribute with the characters []
appended to it. For example, you HTML would look like this:
<label><input type="checkbox" name="animals[]">Cat</label> <label><input type="checkbox" name="animals[]">Dog</label> <label><input type="checkbox" name="animals[]">Horse</label> <label><input type="checkbox" name="animals[]">Llama</label>
Then, when you want to process it with PHP you can access like this:
$cat = $_POST['animals'][0]; $dog = $_POST['animals'][1]; $horse = $_POST['animals'][2]; $llama = $_POST['animals'][3];
This works because when you added the []
to the input element’s name, it became an array in PHP that can be iterated over.
The Select element (<input type="select">
) is rather strait-forward when using a hardcoded list, but you may find the <option>
items are dynamically built from an external datasource. In that case, do not use innerHTML to build the list. Sure, that works fine with real browsers, but stupid, stupid Internet Explorer chokes on it. Use this method instead.
var data = [ {fruit:"Apple",upc:1234}, {fruit:"Banana",upc:5678}, {fruit:"Carrot",upc:9054}]; var selectElem = document.getElementById('mySelect'); var newOption; for (var i=0;i<data.length;i++) { newOption = new Option(data[i].fruit, data[i].upc); /* text, value */ selectElem.add(newOption,null); /* the null means add to end of list */ }
Use the selectedIndex property of the Select element, or loop through each of the options like this:
$('#role option').each(function() { if (this.value == $td.data('role')) { this.selected = true; } });
document.getElementById('mySelect').value; //works when not a multiple select
If multiple selections are allowed, then loop through them.
It is a good idea to validate your form before sending it off to the server, the question is “Where do I place the validation and submission code?”
You could place that in the Submit button’s onClick event or the form’s onSubmit event. The second option is the correct one. There will be problems for screen readers and keyboard navigation if you put your logic in the Submit button’s handler.
Do this:
$("form").submit(function(e) { // Validation code goes here var failsValidation = myCustomValidation(this); if (failsValidation) { e.preventDefault(); // Prevents the form submission } });
K. Burke describes very well how it is possible to make your AJAX powered site still be friendly for people who have Javascript turned off. To do this, make the form action
and method
default to the same endpoint that you are POSTing to with Javascript. You are probably returning some kind of JSON object with an error or success message and then redirecting the user in Javascript. Just change your server endpoint to redirect if the request is not an AJAX request. You can do this because all browsers attach an X-Requested-With: XMLHttpRequest
HTTP header to asynchronous Javascript requests.
Don't change the names of the submitted parameters in Javascript - just submit the same names that you had in your form. In jQuery this is easy, just call the serialize method on the form.
var form = $("#form-id"); $.post('endpoint', $(form).serialize(), function(response) { // do something with the response. });
Look at the code in this example for one way you can email the results of a form using PHP.
SPRY is a JavaScript library created by Adobe to make user interface elements smarter. In the case of form fields, such as textboxes, you can validate the input prior to sending the data to a server. In Dreamweaver, place a SPRY field on your page and then click the blue label above the field. You can now set the validation items for the field. You can choose to validate on “blur”, “change”, and “submit”. Blur is typically when you are exerting extreme control over the field; it almost always better to use the onChange event and onSubmit.
There are two aspects to validation - giving the user feedback when the data entered is bad, and preventing form submission when the data is bad. You don’t need to do anything special to make the validation work, it’s baked into the SPRY fields. However, if you need custom validation that SPRY doesn’t provide (or example, if field A has been filled in, then fields B and C are required, otherwise they are not) then you will need to integrate that logic into Adobe’s SPRY library - I did this once but can’t remember how I did it. Damn it.
See the Date Validation page.
The previous two sections on SPRY are probably now a moot point given that HTML5 Form elements can handle basic validation. More information coming soon...