Self Validating Forms
HTML5 includes additional features for Forms. These include:
- Making Forms friendlier
- Validating Form data.
Form friendliness includes:
- The
placeholder
attribute to offer hints or explanations of requested data. - Specialised input types, such as dates and numbers, which offer specialised interfaces.
In a sense, data validation is also an improvement in friendliness in that it offers immediate feedback rather than requiring the user to wait until the form has been submitted and, possibly, rejected.
Validation
Checking the data is always an important requirement. This ensures that the data is:
- Complete
- Valid
- Safe
Note: The data should always be checked at the server, as it is possible to bypass browser validation. Browser validation is purely a convenience to the user.
Traditionally, browser validation has been provided by JavaScript. Today, it is largely built in to browser in the form of HTML5 features.
JavaScript may still be required to check things that are not currently possible in HTML5 validation. For example:
- Check whether a new email address already exists in the database
- Check how the value in one field compares with the value of another field
What follows is a discussion of how HTML5 validation, together with CSS, can be used to make a more friendly form.
The Form
For our purposes, we will use the following sample form:
<form id="contact" action="" method="post">
<fieldset>
<p><label>From:<br>
<input type="email" name="from"
placeholder="Email Address" maxlength="60" required>
<span>Please enter a valid email address</span>
</label></p>
<p><label>Name:<br>
<input type="text" name="name"
placeholder="Full Name" maxlength="60" required
pattern="\S+\s+\S+.*">
<span>Please enter your full name</span>
</label></p>
<p><label>Phone:<br>
<input type="text" name="phone"
maxlength="30" placeholder="Phone (Optional)"></label></p>
<p><label for="contact-subject">Subject:<br>
<input type="text" name="subject"
maxlength="60" placeholder="Subject" required>
<span>Please enter a subject</span>
</label></p>
<p><label>Message:<br>
<textarea name="message" placeholder="Message" required></textarea>
<span>Please enter a message</span>
</label></p>
</fieldset>
<fieldset id="buttons">
<p><button type="submit" name="send">send message</button></p>
</fieldset>
</form>
The id
attribute is not of itself important for the form. However it will be used to identify this from for CSS and JavaScript.
Attributes
The form above uses the following features.
-
type="email"
This actually achieves two things:
- The value will be checked whether it matches the pattern for an email address.
- On a mobile device, it will often show the specialised email keyboard.
-
placeholder="…"
This is ghostly text which will appear when the value is empty.
-
maxlength="…"
/minlength="…"
Sets limits on the acceptable length of the value
-
required
Indicates that the value cannot be empty.
-
pattern="…"
A regular expression against which the value is checked.
Form elements would also include the following standard attributes:
-
name="…"
The
name
attribute will be associated with the data when the form is submitted to the server, so it is essential for submitting the data. It is also possible to use this attribute locally in CSS and JavaScript. -
id="…"
The
id
attribute never leaves the browser, so is only used locally. Apart from its use in CSS and JavaScript, it can also be used to associate alabel
using thefor
attribute. It is not used in this example.
Constraint Validation
In modern browsers, the form data will be checked against any validation requirements. In the above list, this includes:
type="email"
maxlength="…"
/minlength="…"
required
pattern="…"
Constraint Validation ignores empty fields, unless they are also required. Validation only applies after the user has edited the field value.
The browser will not prevent the user from entering invalid data. However,
- The browser will highlight invalid fields. Using CSS, you can change how this occurs.
- The browser will not submit a form which is not completely valid.
CSS
Two pseudo classes, :valid
and :invalid
are available for styling:
- All validated elements can be selected using the pseudo class
- In some browsers, you can also use the pseudo class on
fieldset
andform
elements, but not all of them.
In addition to this you can use attribute selectors. For example:
… [required] {} /* Required fields */
… [type="email"] {} /* Email fields */
… [name="…"] {} /* One specific field */
The CSS
CSS can be used to highlight elements, as well as help the user with validation.
Invalid Elements
By default, invalid elements are highlighted with a red fuzzy outline. The following CSS will remove this highlight.
Browsers vary in whether the highlight is implemented as an outline or a box shadow.
/* Validation
================================================ */
form#contact input:invalid,
form#contact textarea:invalid {
outline: none;
box-shadow: none;
outline-width: 0;
/* you may wish to add a different style instead … */
}
Required Fields
Naturally, required fields should be marked as such. The following CSS creates a strong border around them.
/* Highlight Required Fields
================================================ */
form#contact input[required],
form#contact textarea[required] {
border: medium solid #999;
}
Validation Message
The default message for validated inputs isn’t very useful. For this reason we include a span
element.
- The
span
element needs to be associated with the input. The most reliable way is:- Put the
span
immediately after the input. - Select the
span
by using the sibling selector (+
).
- Put the
All of this will take place inside the label
element which wraps around the input
and the span
.
- To position the
span
:- set the containing
label
toposition: relative
; this will contain the absolute positioning inside. - set the
span
toposition: absolute
, and adjust the position relative to thelabel
element
- set the containing
We only want to display the validation message at the right time, so we hide it otherwise.
Normally, to hide an element you can use display: none
which virtually removes the element from the layout. However, this will complicate things later, so it is easier to use visibility: hidden
, which will simply hide it without removing it.
- Set the
span
tovisibility: hidden
.
/* Validation Message Box
================================================ */
form#contact label {
position: relative;
}
form#contact textarea+span,
form#contact input+span {
box-sizing: border-box;
font-size: .8em;
font-weight: bold;
position: absolute;
right: 0;
top: .375em;
padding: .25em .75em;
visibility: hidden;
}
Showing the Message
Showing the message all the time can be overwhelming. For that reason, we will show the message when the text box is in focus, or when there is an error.
- To select for an input in focus, use
input:focus
- To select for an invalid input, use
input:invalid
In both cases, we select the span using the sibling selector:
input:focus+span
input:invalid+span
When selected, the message will be displayed by setting the visibility
property:
visibility: visible
The span will be visible when the element is in focus, or, if there is an error, always.
/* Validation Message
================================================ */
form#contact textarea:invalid+span,
form#contact input:invalid+span,
form#contact textarea:focus+span,
form#contact input:focus+span {
visibility: visible;
}
Displaying Validity
If an element is invalid, we will change the message span
to white text on a red background. Otherwise, it will remain with the default styling.
/* Correctness
================================================ */
form#contact textarea:invalid+span,
form#contact input:invalid+span {
background-color: red;
color: white;
border: thin solid red;
}
Displaying the Status
Apart from the stark error message, we will also display a more subtle status by adding a symbol after the message. This will be regardless of whether the actual message span is visible.
The :after
pseudo element can be used to append content to an element.
- Refer to the pseudo element using
span:after
- Since the
span
itself may not be visible, make sure that the:after
pseudo element by settingvisibility: visible
- Add some room with the
margin-left
property.
The status only applies when the data is valid or invalid. This does not include empty data (unless it is required
).
The actual status will be set by setting the content
property to something suitable.
- Select the validated element using
:valid+span:after
or:invalid+span:after
- Set the
content
to something suitable.
/* Satus
================================================
Possible Symbols: ✓ ⁉︎ ☹︎ ☺︎ ‼︎
================================================ */
form#contact :valid+span:after,
form#contact :invalid+span:after {
visibility: visible;
margin-left: 1em;
}
form#contact :valid+span:after {
content: "✓";
color: green;
}
form#contact :invalid+span:after {
content: "⁉︎";
color: white;
font-weight: bold;
}
Disabling the Submit Button
In modern browsers, the form will not submit if there are any validation errors. However, it would be better if the actual Submit button makes the point clear.
- To select the invalid submit button, use the
form:invalid
pseudo class. - Change the appearance of the button with the
opacity
property.
This changes the appearance of the button, but it is still active. To actually deactivate the button, use the pointer-events
property, which will disable clicking:
- Disable the button by setting
pointer-events: none
The bad news is that Neither IE nor Edge support form:invalid
. However, they will still not submit the form, so this is only a minor tragedy.
/* Disable Invalid Form
================================================
Doesn’t work on IE or Edge, of course,
but form will still not submit.
================================================ */
form#contact:invalid button[type="submit"] {
opacity: .3;
pointer-events: none;
}