Course outline · 0% complete

0/30 lessons0%

Course overview →

Forms and inputs

lesson 3-1 · ~10 min · 7/30

From lesson 2-1, in <a href="/apply">Apply</a>, the href="/apply" part is an attribute, a name="value" setting written inside the opening tag.

PieceName
hrefthe attribute name
/applythe attribute value

Forms are built almost entirely out of attributes, so this word is worth keeping close at hand for the rest of the unit.

Forms collect input

Everything built so far only shows content. A form collects it, and collecting input is where the web earns money and gets work done, since every login, search box, checkout, and signup on the internet is a form.

It is also where accessibility and validation bugs cluster, which is why interviewers like asking about the details below.

<form action="/signup" method="post">
  <label for="email">Email</label>
  <input id="email" name="email" type="email">

  <button type="submit">Sign up</button>
</form>
Element or attributeRole
formwraps everything
actionthe URL the data goes to
method="post"send data rather than just fetch a page
inputa void element rendering the field
namethe key the server receives the value under
labelnames the field for humans
formust equal the input's id
button type="submit"submits the form

Pairing the label to the input through for and id, where id is the unique element name from lesson 2-3, is what makes clicking the label focus the input and lets screen readers announce the field properly.

Every input gets a label. An unlabelled field is unusable with assistive technology, and it is the single most common accessibility defect in real forms.

Input types

One element covers many behaviors, because the type attribute changes both the widget and the built-in checks.

typeWhat you get
texta plain one-line text box
emaila text box, and submits without a valid-looking email are blocked
passwordcharacters shown as dots
numbera numeric keyboard on phones, respecting min and max
checkboxan on or off box
radiopick one of a group, given one shared name

Two more form elements round out the set. textarea handles multi-line text, and select with option children builds a dropdown.

Adding the required attribute to any field makes the browser refuse to submit while it is empty. That is free validation before a single line of JavaScript exists, and lesson 9-3 covers the JavaScript version for custom rules.

<label for="email">Email</label><input id="email" type="email">the two strings must match exactlyClicking the word Email now focuses the field, and the field is announced with its name.
The for attribute on a label must repeat the id of its input, which is what makes the text clickable and readable by a screen reader.

What a label pairs with

A label's for attribute must match the input's id.

AttributePairs withPurpose
for on the labelid on the inputlinks them in the browser
name on the inputnothing on the labelthe key the server sees

The name attribute is unrelated to labels, existing only so the submitted data arrives under a known key. Confusing the two produces a form that submits correctly while remaining unusable with a screen reader, which is why the pairing is worth checking deliberately.

A signup form wired up properly

One field, with the label, the id, and the browser's own validation all in place.

HTML

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Signup</title>
  </head>
  <body>
    <h1>Join the study group</h1>
    <form>
      <label for="email">Email</label>
      <input id="email" name="email" type="email" required>
      <button type="submit">Sign up</button>
    </form>
  </body>
</html>
DetailEffect
for="email" matching id="email"clicking the label focuses the field
type="email"a malformed address is rejected
requiredan empty field is rejected

The label comes first, which matches reading order for both sighted and screen reader users. required needs no value, since its presence alone is the setting.

Submitting the form while empty demonstrates both checks at once, with the browser blocking the submit and pointing at the field.

Writing your own email check

The browser's type="email" check is a black box, so a simple version makes the rules explicit. looksLikeEmail(value) is true only for exactly one @, at least one character before it, and a dot somewhere after it.

function looksLikeEmail(value) {
  const at = value.indexOf("@");
  if (at < 1) return false;
  if (value.indexOf("@", at + 1) !== -1) return false;
  return value.indexOf(".", at + 1) !== -1;
}

console.log(looksLikeEmail("ada@example.com"));
console.log(looksLikeEmail("ada@examplecom"));
console.log(looksLikeEmail("@example.com"));
console.log(looksLikeEmail("ada@ex@ample.com"));

Output

true
false
false
false
InputFails on
ada@example.comnothing, it passes
ada@examplecomno dot after the @
@example.comnothing before the @
ada@ex@ample.coma second @

indexOf("@") returns the position of the first @, or -1 when there is none, and both 0 and -1 fail the at-least-one-character rule in a single comparison.

Passing a start position, as in indexOf("@", at + 1), searches for a second @ after the first, and finding one rejects the value. The final rule is one line, and the whole function shows why real email validation is famously harder than it looks.