The following is an extract from our book, HTML5 & CSS3 for the Real World, 2nd Edition, written by Alexis Goldstein, Louis Lazaris, and Estelle Weyl. Copies are sold in stores worldwide, or you can buy it in ebook form here.

The required Attribute

The Boolean required attribute tells the browser to only submit the form if the field in question is filled out. Obviously, this means that the field can’t be left empty, but it also means that, depending on other attributes or the field’s type, only certain types of values will be accepted. Later in the chapter, we’ll be covering different ways of letting browsers know what kind of data is expected in a form.

If a required field is empty the form will fail to submit. Opera, Firefox, Internet Explorer 10+, and Chrome provide the user with error messages; for example, “Please fill out this field” or “You have to specify a value” if left empty.

Note: Time to Focus

Time for a quick refresher: a form element is focused either when users click on the field with their mouse, tap into the field with their finger on a touch device, tab to it with their keyboard, or click or touches the label associated with that form element. For input elements, typing with the keyboard will enter data into that element.

In JavaScript focus event terminology, the focusevent will fire on a form element when it receives focus, and the blur event will fire when it losesfocus.

In CSS, the :focus pseudo-class can be used to style elements that currently have focus.

The required attribute is valid on any input type except button,submit, image, range, color, and hidden, all of which generally have a default value so the attribute would be redundant. As with other Boolean attributes we’ve seen so far, the syntax is either simply required, or required="required" if you’re using XHTML syntax.

Let’s add the required attribute to our sign-up form. We’ll make the name, email address, password, and subscription start date fields required:

<ul>
  <li>
    <label for="register-name">My name is:</label>
    <input type="text" id="register-name" name="name" required aria-
↵required="true">
  </li>
  <li>
    <label for="email">My email address is:</label>
    <input type="text" id="email" name="email" required aria-
↵required="true">
  </li>
  <li>
    <label for="url">My website is located at:</label>
    <input type="text" id="url" name="url">
  </li>
  <li> 
    <label for="password">I would like my password to be:</label>
    <p>(at least 6 characters, no spaces)</p>
    <input type="password" id="password" name="password" required 
↵aria-required="true">
  </li>
  <li>
    <label for="rating">On a scale of 1 to 10, my knowledge of 
↵HTML5 is:</label>
    <input type="text" name="rating" type="range">
  </li>
  <li>
    <label for="startdate">Please start my subscription on:
↵</label>
    <input type="text" id="startdate" name="startdate" required aria
↵-required="true">
  </li>
  <li>
    <label for="quantity">I would like to receive <input 
↵type="text" name="quantity" id="quantity"> copies of <cite> 
↵The HTML5 Herald</cite></label>
  </li>
  <li>
    <label for="upsell">Also sign me up for <cite>The CSS3 
↵Chronicle</cite></label>
    <input type="checkbox" id="upsell" name="upsell" 
↵value="CSS Chronicle">
  </li>
  <li>
    <input type="submit" id="register-submit" value="Send Post 
↵Haste">
  </li>
</ul>

Note: Improving Accessibility

You can include the WAI-ARIA attribute aria-required="true" for improved accessibility; however, as most browsers and screen readers now natively support the required attribute, this will soon by unnecessary. See Appendix B for a brief introduction to WAI-ARIA.

Figure 4.1, Figure 4.2, and Figure 4.3 show the behavior of the required attribute when you attempt to submit the form.

Figure 4.1. The required field validation message in Firefox

Figure 4.1. The required field validation message in Firefox

Figure 4.2. How it looks in Opera …

Figure 4.2. How it looks in Opera …

Figure 4.3. … and in Google Chrome

Figure 4.3. … and in Google Chrome

Styling Required Form Fields

You can style required form elements with the :required pseudo-class, and optional form elements with the :optional pseudo-class (or use the negation pseudo-class :not(:required)). You can also style valid and invalid fields with the :valid and:invalid pseudo-classes respectively. With these pseudo-classes and a little CSS magic, you provide visual cues to sighted users indicating which fields are required, and give feedback for successful data entry:

input {
  background-position: 0% 50%;
  background-repeat: no-repeat;
  padding-left: 15px;
}
input:required {
  background-image: url('../images/required.png');
}
input:focus:invalid { 
  background-image: url('../images/invalid.png');
} 
input:focus:valid { 
  background-image: url('../images/valid.png');
}

We’re adding a background image (an asterisk) to required form fields. We can’t include generated content on an input as they’re replaced or empty elements, so we use a background image instead. We’ve also added separate background images to valid and invalid fields. The change is only apparent when the form element has focus, to keep the form from looking too cluttered.

Warning: Firefox Applies Styles to Invalid Elements

Note that Firefox applies its own styles to invalid elements (a red shadow), as shown in Figure 4.1 earlier. You may want to remove the native drop shadow with the following CSS:

:invalid { box-shadow: none; }

Tip: Targeted Styles for Older Browsers

Older browsers such as IE8 and IE9 don’t support the :required pseudo-class, but you can still provide targeted styles using the attribute selector:

input:required,
input[required] {
  background-image: url('../images/required.png');
}

You can also use this attribute as a hook for form validation in browsers without support for HTML5 form validation. Your JavaScript code can check for the presence of the required attribute on value-less inputs, and not submit the form if any are found.

The placeholder Attribute

The placeholder attribute allows a short hint to be displayed inside the form element—space permitting—telling the user what type of data should be entered in that field. The placeholder text disappears when the field gains focus and the user enters at least one character, and reappears when the value is null. Developers have provided similar functionality with JavaScript for years―adding a temporary value, then clearing the value on focus―but in HTML5 the placeholder attribute allows it to happen natively with no JavaScript required, and stays present until a value is entered.

For The HTML5 Herald’s sign-up form, we’ll put a placeholder on the website URL and start date fields:

<li>
  <label for="url">My website is located at:</label>
  <input type="text" id="url" name="url" 
↵ placeholder="e.g. http://example.com">
</li>
…
<li>
  <label for="startdate">Please start my subscription on:</label>
  <input type="text" id="startdate" name="startdate" required 
↵aria-required="true" >
</li>

In Internet Explorer, because the placeholder attribute only received support in IE10, and because the placeholder text disappears once the user enters data, you shouldn’t rely on it as the only way to inform users of requirements. If your hint exceeds the size of the field, describe the requirements in the input’s title attribute, in the label or in text next to the input element. Some developers suggest adding “e.g.” as part of the placeholder text to make it evident that it’s placeholder text and not actually prefilled data.

All browsers starting with Safari 4, Chrome 10, Opera 11.1, Firefox 4, Android 2.3, and Internet Explorer 10 support the placeholder attribute, though the original implementation ofplaceholder removed the placeholder text on focus rather than on data entry.

Polyfilling Support with JavaScript

Like everything else in this chapter, it won’t hurt to include theplaceholder attribute even when dealing with older browsers that lack support.

As with the required attribute, you can make use of theplaceholder attribute and its value to make older versions of Internet Explorer behave as if they supported it—all by using a little JavaScript polyfill magic.

Here’s how you’d go about it: first, use JavaScript to determine which browsers are without support. Then, in those browsers, use a function that creates a faux placeholder. The function needs to determine which form fields contain the placeholderattribute, then temporarily grab that attribute’s content and replace empty value attributes with that text.

Then you need to set up two event handlers: one to clear the field’s value on focus, and another to replace the placeholdervalue on blur if the form control’s value is still an empty string. If you do use this trick, make sure that the value of your placeholder attribute isn’t one that users might actually enter, or alternatively use the “e.g.” precursor to indicate that the placeholder is an example and not a valid value. Additionally, remember to clear the faux placeholder when the form is submitted. Otherwise, you’ll have lots of “(XXX) XXX-XXXX” submissions!

Let’s look at a sample JavaScript snippet to progressively enhance our form elements using the placeholder attribute.

Here’s our placeholder polyfill:

<script>
  // check if supported
  if(!Modernizr.input.placeholder) {
  // get all the form controls with the placeholder attribute
  var fcToCheck = document.querySelectorAll("*[placeholder]"),
      frmsToCheck = document.querySelectorAll('form'),
      i, count;

  // loop through form controls with placeholder attribute,
  // copy placeholder value into value, clearing on focus and
  // resetting, if empty, on blur
  for(var i = 0, count = fcToCheck.length; i < count; i++) {
    if(fcToCheck[i].value == "") {
      fcToCheck[i].value = fcToCheck[i].getAttribute("placeholder");
      fcToCheck[i].classList.add('placeholder');
      fcToCheck[i].addEventListener('focus', function() {
          if (this.value==this.getAttribute("placeholder")) {
            this.value = '';
            this.classList.remove('placeholder');
        }
      });
      fcToCheck[i].addEventListener('blur', function() {
        if (this.value == '') {
            this.value = this.getAttribute("placeholder");
            this.classList.add('placeholder');
        }
      });
    }
  }

  for(i = 0, count = frmsToCheck.length; i < count; i++) {

    frmsToCheck[i].addEventListener('submit', function(e) {
      var i, count, plcHld;

    // first do all the checking for required
    // element and form validation.
    // Only remove placeholders before final submission
      plcHld = this.querySelectorAll('[placeholder]');
      for(i = 0, count = plcHld.length; i < count; i++){
        //if the placeholder still equals the value
        if(plcHld[i].value == plcHld[i].getAttribute(
↵'placeholder')){
          // don't submit if required
          if(plcHld[i].hasAttribute('required')) {
            // create error messaging
            plcHld[i].classList.add('error');
            e.preventDefault();
          } else {
            // if not required, clear value before submitting.
            plcHld[i].value = '';
          }
        } else {
            // remove legacy error messaging
            plcHld[i].classList.remove('error');
        }
      }
    });
  }
</script>

The first point to note about this script is that we’re using theModernizr JavaScript library to detect support for the placeholderattribute. There’s more information about Modernizr in Appendix A, but for now it’s enough to understand that it provides you with a whole raft of true or false properties for the presence of given HTML5 and CSS3 features in the browser. In this case, the property we’re using is fairly self-explanatory.Modernizr.input.placeholder will be true if the browser supportsplaceholder, and false if it doesn’t.

If we’ve determined that placeholder support is absent, we grab all the elements on the page with a placeholder attribute. For each of them, we check that the value isn’t empty, then replace that value with the value of the placeholder attribute. In the process, we add the placeholder class to the element, so you can lighten the color of the font in your CSS or otherwise make it look more like a native placeholder. When the user focuses on the input with the faux placeholder, the script clears the value and removes the class. When the user removes focus, the script checks to see if there is a value. If not, we add the placeholder text and class back in.

Before submitting the form, we need to check if any form controls have a value that matches their placeholder attribute. In this scenario, we could have also checked to see whether any required input still has the placeholder class when the form is submitted. If a form control is required, we add error messaging and prevent the form from submitting. If the form control isn’t required, we clear the placeholder values that are still in place before submitting, only clearing those if no required elements have prevented form submission.

Before adding a reset button to your form, determine whether your users will ever want to throw away all of their work. If the answer is yes and you include a reset button, note that if the user clicks on the reset button, our faux placeholders will disappear but the placeholder class will remain, as we are using the value in our polyfill.

This is a great example of an HTML5 polyfill: we use JavaScript to provide support only for those browsers without native support, and we do it by leveraging the HTML5 elements and attributes already in place, rather than resorting to additional classes or hard-coded values in our JavaScript.

While the placeholder attribute may not be the most important one to polyfill, it’s a good example of how we can simplify form validation scripts while polyfilling support for all the new attributes, all while maintaining separation between the content and presentation layers.

Sponsors