# Exercise: Fix the Frustrating Sign-Up Form

Fix Peak Fitness's frustrating sign-up form with real labels, the right types, autocomplete, hints and required fields marked in words, then let the checks and a keyboard-only run prove it works.

Journeyman · HTML · Web Development · Updated October 30, 2026

Peak Fitness, a made-up gym, offers a free first week, and half the people who start its sign-up form never finish it. The form isn't broken: it sends, and the gym gets the answers. It's frustrating. The labels vanish as you type, every box brings up the same keyboard, nothing fills itself in, the ZIP code refuses answers without saying why, and the **Clear** button sits right next to **Submit**. Your job is to fix it with HTML alone, then check it the way real people use it: with the keyboard, and on a phone.

## Get the exercise code

In the **Exercise** box beside the lesson, choose **Get the starter on GitHub** to open its GitHub repository. Click **Code**, then **Download ZIP**, and unzip it into the folder where you keep your web projects.

The folder holds:

- `signup.html`: the sign-up form, for you to fix. The comment at the top lists what to fix.
- `received.html`: shows, as a table, what the form sent. Ready to use.
- `style.css`: the gym's ready-made stylesheet. It styles plain HTML, so the form looks good as soon as its HTML is right. Ready to use.
- `signup.test.js` and `package.json`: the checks. You don't need to change these.

Open the folder in VS Code. Open a terminal (**Terminal > New Terminal**) and type `npm install` once, to download the two small tools the checks use.

## What to do

Every field in the starter looks like this one: a text box with a placeholder, and nothing else.

```html
<div>
  <input type="text" name="zip" placeholder="ZIP code" pattern="[0-9]{5}">
</div>
```

1. **Give every field a real label.** Each field gets an `id` and a `<label for="that id">` with words in it. Keep every `name` as it is: `received.html` shows the answers by those names.
2. **Give every field the type that fits its answer.** Email, phone, birth date and password each have a type of their own. The membership plan is one choice from three: Basic ($25 a month), Plus ($40) and Premium ($60). A ZIP code stays text.
3. **Let the browser and the phone help.** Add `autocomplete` to the name, email, phone, birth date, ZIP code and password, and `inputmode="numeric"` to the ZIP code.
4. **Explain the rules people can't see.** The ZIP code has a `pattern` and the password a `minlength`. Give each one a hint that says what to type, tied to its field with `aria-describedby`.
5. **Say "required" in words.** Remove the "Required fields in red" note, and put "(required)" in the label of every required field.
6. **Remove the reset button,** and give the submit button words that say what happens.
7. **Try it the way people use it.**
   - **With the keyboard only.** Put the mouse away. Press **Tab** to move from field to field, **Space** to pick a radio button or check a box, and **Enter** to send. Can you reach and answer everything, in an order that makes sense?
   - **On a phone-sized screen.** Press **F12**, then turn on the device toolbar (**Ctrl+Shift+M**, or **Cmd+Shift+M** on a Mac) and pick a phone from the list at the top. Is the form one column, and is every label next to its field?

## Check your work

Right-click `signup.html` and choose **Open with Live Server**. Fill in the form with made-up answers and send it: `received.html` shows what the gym would get. Never type a real password into a practice form. This exercise's form uses `method="get"` only so `received.html` can read the answers from the address. A real sign-up form sends by POST, as in *How a Form Sends Data*.

Then run the checks in the terminal:

```bash
npm test
```

At first almost every check fails. That's expected: each fix turns its check green. A failing check's message says which field it looked at and what it expected, for example *The "email" field should be type="email".* The last check runs the HTML validator, and its messages name the line to look at.

## Hints

- **A placeholder is not a label.** It disappears as soon as someone types. *Hints and Error Messages Everyone Can Use* explains what a screen reader hears instead.
- **Radio buttons that answer one question share one `name`.** Group them in a `<fieldset>` whose `<legend>` asks the question, and put "(required)" there.
- **Look up autocomplete values; don't guess them.** A made-up value is ignored. The table in *Autocomplete and Phone Keyboards* has every one you need, and a sign-up form's password is a new one.
- **A hint needs an `id`.** The field's `aria-describedby` names that `id`, with no `#`.
- **Fix the validator's first message first.** One missing label can cause more than one message.

## When you're done

The form is one column with a label above every field, the phone shows a number pad for the ZIP code, and every check is green:

```text
✔ 1) every field keeps its name, so received.html can show it (6.7041ms)
✔ 2) every field has a real label (3.8729ms)
✔ 3) every field has the type that fits its answer (0.7949ms)
✔ 4) the plan is one choice from three, grouped with a question (2.991ms)
✔ 5) autocomplete tells the browser what each field is (0.9444ms)
✔ 6) the ZIP code brings up the number keypad on a phone (0.2848ms)
✔ 7) every rule a person can't see has a hint tied to its field (1.6699ms)
✔ 8) required fields say so in words, not color alone (1.5874ms)
✔ 9) no reset button (2.106ms)
✔ 10) the validator finds no errors (102.28ms)
ℹ tests 10
ℹ suites 0
ℹ pass 10
ℹ fail 0
```

The times in parentheses will be different on your computer, and a few more summary lines follow. Now look back at your form: if someone removed every `required` and `pattern` in the developer tools, what would Peak Fitness's server have to check before it saves a new member?

## So what

You fixed a form the way real teams do: not by redesigning it, but by labeling fields, choosing types, helping the browser and the phone, and checking it with a keyboard and a small screen. Every sign-up, checkout and application form you build from here starts with these habits.

## What's next

The Module 3 mini-capstone is **A Pet Adoption Application** for Happy Tails Rescue, a made-up animal shelter. You build the whole form on one page: contact details with autocomplete, the pet you'd like to meet (radio buttons with each pet's photo and name), your home (fieldsets, a dropdown, checkboxes for other pets), a day and time to visit, a "tell us about yourself" box and a required agreement. Every field has a label and a hint where it helps, the browser checks every answer, and it works with the keyboard alone and on a phone. It sends to a `received.html` page that shows what the shelter would get.

Module 4 fills your pages with pictures, video and sound, and makes them load fast on a phone: sharp photos in the right sizes, video with captions, and pages that appear before people lose patience.

## Key terms

- [autocomplete](https://www.ask-codey.com/glossary/autocomplete)
- [inputmode](https://www.ask-codey.com/glossary/inputmode)
- [aria-describedby](https://www.ask-codey.com/glossary/aria-describedby)
- [pattern](https://www.ask-codey.com/glossary/pattern)
- [required](https://www.ask-codey.com/glossary/required)
- [Accessible name](https://www.ask-codey.com/glossary/accessible-name)

## Related

- [Built-in Validation](https://www.ask-codey.com/lessons/html-forms-built-in-validation)
- [Why the Server Checks Again](https://www.ask-codey.com/lessons/html-forms-why-the-server-checks-again)
- [Autocomplete and Phone Keyboards](https://www.ask-codey.com/lessons/html-forms-autocomplete-and-input-modes)
- [Hints and Error Messages Everyone Can Use](https://www.ask-codey.com/lessons/html-forms-hints-and-error-messages)

Source: https://www.ask-codey.com/lessons/exercise-html-fix-the-sign-up-form
