Arkendia Classrooms
Lesson 7 of 21 · 20 min

Building complete HTML forms

A portfolio without a way to get in touch is a missed opportunity. In this lesson you will build a complete contact form: labels, the many types of fields, built-in validation, dropdowns, grouped options and buttons. You will also learn what a form does when it is submitted, and what it cannot do without a server.

What a form is

A form element wraps a set of controls that visitors fill in. When they press the submit button, the browser collects the values and sends them to an address. Two attributes tell it how:

  • action: the address that will receive the data.
  • method: how the data is sent. get puts the values in the address (suitable for searches), post sends them in the body of the request (suitable for messages and anything private).
<form action="/send-message" method="post">
  ...
</form>

Labels: the golden rule

Every field needs a label. It tells the visitor what to type, enlarges the click area (clicking the label puts the cursor in the field) and is read aloud by screen readers. There are two equivalent ways to link them:

<label for="name">Your name</label>
<input type="text" id="name" name="name">

<label>Your name <input type="text" name="name"></label>

The first links by matching for and id. The second wraps the field inside the label. A placeholder attribute shows a hint inside an empty field, but it is not a replacement for a label: it disappears when typing, and is often low in contrast.

The input element and its types

The void element input changes behavior based on its type. Choosing the right type gives you proper keyboards on phones, built-in checks and better accessibility for free.

TypeUse
textA single line of text (default)
emailAn email address; checks the format and shows a suitable keyboard
telA phone number
urlA web address
passwordHides the characters
numberA number, with optional min, max and step
dateA date picker
checkboxAn option that can be ticked, independently of others
radioOne choice among several
fileUpload a file
searchA search field

The name attribute is the key under which the value is sent. A field without a name is simply not submitted.

Longer text: textarea

For multi-line messages, use textarea. It has an opening and closing tag, and rows sets its visible height:

<label for="message">Your message</label>
<textarea id="message" name="message" rows="6"></textarea>

Choices: select, checkbox and radio

A dropdown list uses select with option elements:

<label for="topic">Subject</label>
<select id="topic" name="topic">
  <option value="">Choose a subject</option>
  <option value="portrait">Portrait session</option>
  <option value="illustration">Illustration request</option>
  <option value="other">Something else</option>
</select>

The value is what gets sent; the text between the tags is what the visitor sees.

Radio buttons let the visitor choose exactly one option. Buttons are tied into a group by sharing the same name:

<fieldset>
  <legend>How would you like me to reply?</legend>
  <label><input type="radio" name="reply" value="email" checked> By email</label>
  <label><input type="radio" name="reply" value="phone"> By phone</label>
</fieldset>

A fieldset groups related controls and its legend gives the group a name. It is especially important for radio buttons and checkboxes, so that screen readers announce the question along with each option. Checkboxes work like radio buttons but allow several to be ticked:

<label><input type="checkbox" name="newsletter" value="yes"> Send me news about new projects</label>

Built-in validation

Browsers can check input before sending, without any JavaScript. You add constraints with attributes:

  • required: the field must be filled in.
  • minlength and maxlength: limits on text length.
  • min and max: limits for numbers and dates.
  • pattern: a regular expression the value must match.
  • type="email" and type="url": format checks.
<label for="email">Email address</label>
<input type="email" id="email" name="email" required autocomplete="email">

<label for="subject">Subject (at least 5 characters)</label>
<input type="text" id="subject" name="subject" required minlength="5">

The autocomplete attribute helps the browser pre-fill known information such as name and email, saving people time and effort.

Warning. Browser validation improves the experience but is not security. A determined person can bypass it, so any server that receives the data must check it again. Never trust data only because the form “required” it.

Buttons

The button element triggers an action. Its type matters:

  • type="submit": sends the form (the default inside a form).
  • type="reset": clears all fields. Rarely helpful, since it can erase work by accident.
  • type="button": does nothing by itself; used with JavaScript.

Use a button for actions and a link for navigation. Write a clear label: “Send message” is better than “Submit”.

What happens when you submit?

With method="post", the browser sends the data to the action address, and something on that server must receive it. HTML alone cannot save a message or send an email. There are several common solutions: a server-side program you write or host, or a form-handling service that gives you an address to put in action. A mailto: action opens the visitor’s email program, but behavior is unreliable and exposes your address, so it is not recommended for a real contact form.

In this course, the form on your portfolio will not be connected to anything yet. That is fine: you are learning the structure, which stays the same whatever service you connect later. If you use a third-party service, read its privacy terms, because you will be collecting personal data from your visitors, and in many countries rules such as the GDPR apply.

A complete contact form

<form action="#" method="post">
  <p>
    <label for="c-name">Your name</label>
    <input type="text" id="c-name" name="name" required autocomplete="name">
  </p>
  <p>
    <label for="c-email">Your email</label>
    <input type="email" id="c-email" name="email" required autocomplete="email">
  </p>
  <p>
    <label for="c-topic">Subject</label>
    <select id="c-topic" name="topic">
      <option value="portrait">Portrait session</option>
      <option value="illustration">Illustration request</option>
      <option value="other">Something else</option>
    </select>
  </p>
  <p>
    <label for="c-message">Your message</label>
    <textarea id="c-message" name="message" rows="6" required minlength="10"></textarea>
  </p>
  <p>
    <label><input type="checkbox" name="consent" required> I agree to be contacted about my request</label>
  </p>
  <button type="submit">Send message</button>
</form>

Wrapping each label-and-field pair in a paragraph is a simple way to stack them without CSS. Later you will use a different wrapper and style it properly.

Tip. Test your form with the keyboard only: press Tab to move between fields, Space to tick a box, Enter to submit. If you can fill and send it without a mouse, you have a more accessible form.

Your turn

  1. Create contact.html with your header, nav and footer, and a main containing an h1 and a form.
  2. Add fields for name, email, subject (a select), message (textarea) and a consent checkbox, each with a linked label.
  3. Make name, email and message required, and the message at least 10 characters long.
  4. Add a group of radio buttons in a fieldset to choose a preferred reply method.
  5. Submit the empty form and observe the validation messages, then fill it in correctly.
See a solution

Start from the complete form above and add the radio group between the subject and the message:

<fieldset>
  <legend>Preferred reply</legend>
  <label><input type="radio" name="reply" value="email" checked> Email</label>
  <label><input type="radio" name="reply" value="phone"> Phone</label>
</fieldset>

When you submit with an empty required field, the browser blocks the sending and highlights the first problem with a message. Typing something that does not look like an email in the email field gives another message. If nothing happens when you press the button, check that the button is inside the form element and that its type is submit.

Key takeaways

  • Every field has a visible label linked by for and id (or by wrapping); a placeholder is not a label.
  • Choose the right input type (email, tel, number, date…) and give each field a name.
  • Use select, radio, checkbox and fieldset with legend to offer choices.
  • required, minlength, pattern and typed inputs give native validation, which does not replace server checks.
  • HTML only describes the form: a server or service must receive and process the data.
Advertisement
Log in to save your progress. Log in