What are you building, and who will use it?
You are building the sign-up form for the Riverside Night Run, a free 5 km social run on a November evening. The organisers need each runner's name and email, which pace group they want, and a promise to bring a light. The form will be filled in on phones, often in a hurry, by people of all ages.
That audience sets the bar. Every field needs a label that a screen reader announces. The email field should bring up the email keyboard on a phone. The pace choice should be one tap. The browser should stop an incomplete sign-up before it reaches the server, with a message that points at the problem.
Nothing here is new. The Forms group already gave you every piece. The work is choosing the right piece for each question and fitting them together so the form is quick for runners and useful for organisers. The checker accepts any reasonable version, so your field names and wording can differ from the solution.
How should you plan the form before typing?
Start with the data, not the HTML. Write down each question the organisers need answered, the kind of answer it expects, and whether it is required. That table decides almost every element and attribute for you.
<form action="/signup" method="post">
<!-- name, email, pace, size, safety, notes -->
<button type="submit">Save my place</button>
</form>- Full name: free text, required,
autocomplete="name". - Email: an email address, required,
type="email"andautocomplete="email". - Pace group: one choice from three or four fixed options, required. Radio buttons if there are few options, a
<select>if there are many. - T-shirt size, optional: one choice from a list, so a
<select>with a blank first option. - Safety agreement: yes or no, required, so a single checkbox with
required. - Anything else to tell us: optional long text, so a
<textarea>.
Which earlier lessons does each part use?
Each line of the plan maps back to a lesson. If a part of the form does not behave, reread that lesson before searching elsewhere, because the answer is almost always there.
- Forms: the
<form>withactionandmethod="post", because a sign-up stores personal data. Every control needs anameor it is not sent. - Forms again: a
<label>for every control, connected withforandidor by wrapping the input. - Input types:
type="email"for the address, which checks the format and shows the right phone keyboard.type="tel"if you also collect an emergency number. - Checkboxes and radios: radio buttons that share one
name, grouped in a<fieldset>with a<legend>that asks the question. A<select>for the T-shirt size. - Form validation:
requiredon the fields that must be filled, andmaxlengthon the notes so nobody pastes an essay. - Buttons or links: one
<button type="submit">with text that says what happens, such as "Save my place". - Page layout: the form sits inside
<main>, under the heading that names the event.


name becomes the key the organisers receive. The three pace radios share name="pace", so only one answer is sent.How do radio buttons, the select and the checkbox fit together?
Radio buttons work as a group only when they share a name. Give each a different value, because the value is what the server receives. Put required on at least one radio in the group and the browser will insist that one is chosen. Wrap the group in a <fieldset> and put the question in its <legend>. A screen reader then announces "Pace group, Easy, radio button, 1 of 3", which gives the answer its question.
A <select> is better for longer lists, such as six T-shirt sizes. Start it with an empty option such as "Choose a size" with value="". If the select is required, that empty value counts as not answered, so the browser blocks submission until a real size is picked.
A single checkbox for the safety rules is a yes or no question. If it is unchecked, nothing is sent for it at all. Adding required turns it into an agreement the runner must tick. The label text should state the promise in full so people know what they are agreeing to.
<fieldset>
<legend>Pace group</legend>
<label><input type="radio" name="pace" value="easy" required> Easy</label>
<label><input type="radio" name="pace" value="steady"> Steady</label>
<label><input type="radio" name="pace" value="fast"> Fast</label>
</fieldset>How much validation does the form need?
Enough to catch honest mistakes, and no more. Mark only the fields the organisers truly need as required. Every extra required field is one more reason for a runner to give up halfway. Tell people which fields are optional in the label text, such as "T-shirt size (optional)", so nobody has to guess.
Lean on the input type before reaching for pattern. The type="email" field already rejects "sam.example.com". A custom pattern for email addresses usually rejects real addresses with plus signs or long domains, which loses you sign-ups.
Remember that browser validation is a convenience for the person typing. Anyone can turn it off in DevTools or send a request without the form. The server must check everything again. Your HTML job is to make correct answers easy and mistakes obvious.
How do you check your own work?
Run the checker, then test the form the way a real runner would. These checks take two minutes and catch most problems.
- Click every label. The cursor should land in the matching field, and clicking a radio label should select that radio.
- Press Submit with everything empty. The browser should stop on the first required field and show a message.
- Type "sam" into the email field and submit. The browser should complain about the format.
- Use only the keyboard: Tab between fields, arrow keys inside the radio group, Space to tick the checkbox, Enter to submit.
- Open DevTools, go to the Network panel, fill the form and submit. The request payload should list every field by its
name. A missing key means a missingname. - Open the form on a phone or in the device toolbar. The email field should bring up a keyboard with an @ key.
Where do sign-up forms usually go wrong?
Placeholder text used as the only label is the most common problem. It vanishes as soon as typing starts, and many screen readers treat it as a weak hint at best. Use a real <label> and keep the placeholder for an example, if you use one at all.
Radio buttons with different name values are the next. Each one becomes its own group, so a runner can pick all three pace groups and none can be unticked. The fix is one shared name.
Other frequent faults: a button with type="button" that does nothing when pressed, a <div> styled to look like a button, fields with an id but no name, and a method left off so personal details end up in the URL. AI-generated forms show all of these, plus labels whose for points at an id that does not exist. Read every for and id pair by eye.
What can you add once the basics pass?
Pick one or two stretch ideas and build them from memory before checking the lesson they come from.
- Add a T-shirt size
<select>with an empty first option, and decide whether it should be required. - Add an emergency contact number with
type="tel"andautocomplete="tel". - Add a notes
<textarea>withmaxlength="300"and a hint paragraph connected witharia-describedby. - Add an age check with
type="number",min="16"andmax="99". - Group name and email in their own
<fieldset>with the legend "About you". - Put the event date in a
<time datetime="2026-11-14T19:00">element in the intro. - Add a
<details>element under the form that answers "What if it rains?".
Field notes
- Plan each question, its answer type and whether it is required before writing HTML.
- Radio buttons need a shared
nameand a differentvaluefor each option. - Mark only the fields the organisers truly need as
required.
Easy to get wrong
A placeholder disappears on typing and is not a reliable accessible name. A connected label stays visible and is read aloud.
Radios only form a group when they share one name. Each also needs a value so the server knows which was chosen.
Without a name the field is never sent, so the organisers receive a sign-up with no email address.
A div cannot be focused with the keyboard and does not submit the form. A real button does both with no extra code.
Questions people ask
Should an event sign-up form use GET or POST?
Use POST. The form stores personal details, and GET would put the name and email in the URL, browser history and server logs.
How do I make a checkbox mandatory?
Add the required attribute to the checkbox. The browser will block submission until it is ticked.
Radio buttons or a dropdown for a few options?
Use radio buttons for up to about five options, since all choices stay visible and need one tap. Use a select for longer lists.
Is HTML validation enough to protect my sign-up list?
No. It helps honest users fix mistakes, but anyone can bypass it. The server must validate every field again.
Why does my form submit with a field missing?
Check that the field has required, that it sits inside the form, and that the form does not have novalidate.