We’re moving to a new home! Our website is currently in test mode while we update and transfer our content. Some pages and resources may be temporarily unavailable. We’ll be back with all resources shortly. Thank you for your patience.

HTML & CSS | 02 FORMS AND CONTENT

Put your HTML skills to work

Build tables, design forms, test validation and add accessible media. Try each challenge before opening its hint or sample solution.

YOUR CHALLENGE ROUTE

From structured data to a workshop information page

Work in your editor and browser. Start with the foundation challenges, then move on to repair tasks and the final project. You can spread the work across several lessons.

Use fictional details and images you own or are allowed to publish. Focus on clear HTML structure; detailed CSS styling comes later.

0 / 8 challenges checked.

Your checks last while this page is open. They record your self-review, not an automatic code score.

CHALLENGE 01 | FOUNDATION

Make results easy to compare

Use 02.1 | Tables for tabular data

Create results.html. Build a table for three fictional teams: Falcons scored 42 driver points and 18 autonomous points; Comets scored 38 and 24; Meteors scored 30 and 20. Include a total-points column.

Success criteria

  • Use a caption describing the results.
  • Group header rows in thead and data rows in tbody.
  • Use th with scope="col" for column headings and scope="row" for team labels.
  • Calculate the team totals yourself.
  • Add a tfoot row containing numeric column totals.
Need a hint?

There are four columns: team, driver points, autonomous points and total points. HTML will not calculate totals automatically.

Reveal a sample solution
<table>
  <caption>Robotics skills results</caption>
  <thead>
    <tr>
      <th scope="col">Team</th>
      <th scope="col">Driver points</th>
      <th scope="col">Autonomous points</th>
      <th scope="col">Total points</th>
    </tr>
  </thead>
  <tbody>
    <tr><th scope="row">Falcons</th><td>42</td><td>18</td><td>60</td></tr>
    <tr><th scope="row">Comets</th><td>38</td><td>24</td><td>62</td></tr>
    <tr><th scope="row">Meteors</th><td>30</td><td>20</td><td>50</td></tr>
  </tbody>
  <tfoot>
    <tr><th scope="row">Combined points</th><td>110</td><td>62</td><td>172</td></tr>
  </tfoot>
</table>

CHALLENGE 02 | BUILD

Plan a shared workshop session

Use 02.1 | Spanning cells

Create a timetable with columns for Time, Room A and Room B. At 09:00 both rooms share a safety briefing. At 09:30, Room A builds chassis while Room B programs sensors.

Success criteria

  • Give the timetable a caption and suitable headers.
  • Use colspan="2" for the shared briefing.
  • Every row occupies three column positions.
  • Do not add an extra cell after the spanning cell.
  • Explain why a simple timetable can be easier to navigate than a complicated merged layout.
Need a hint?

The time cell occupies one column. The briefing cell occupies the other two.

Reveal a sample solution
<table>
  <caption>Saturday workshop timetable</caption>
  <thead>
    <tr><th scope="col">Time</th><th scope="col">Room A</th><th scope="col">Room B</th></tr>
  </thead>
  <tbody>
    <tr><th scope="row">09:00</th><td colspan="2">Shared safety briefing</td></tr>
    <tr><th scope="row">09:30</th><td>Build chassis</td><td>Program sensors</td></tr>
  </tbody>
</table>

Use merged cells only when they communicate a genuine relationship. Simple tables make header associations and navigation easier to understand.

CHALLENGE 03 | BUILD

Build a clearly labelled booking form

Use 02.2 | Forms and controls

Create booking.html with a form for a fictional workshop. Collect a team name, email address, one session choice, any equipment interests and a multi-line project idea. This is an interface exercise, not a live booking service.

Success criteria

  • Every control has an associated visible label.
  • Use meaningful names for submitted fields.
  • Session radio buttons share a name and have different values.
  • Independent equipment checkboxes allow multiple selections.
  • Use fieldset and legend for related choices.
  • Give the submit button an explicit type.
Need a hint?

Labels can use matching for and id values or wrap their controls. Keep ids unique, even where names are shared.

Reveal a sample solution
<form action="/workshop-booking" method="post">
  <p><label for="team">Team name</label>
     <input type="text" id="team" name="team_name"></p>
  <p><label for="email">Email address</label>
     <input type="email" id="email" name="email"></p>
  <fieldset>
    <legend>Choose one session</legend>
    <label><input type="radio" name="session" value="build"> Building</label>
    <label><input type="radio" name="session" value="code"> Coding</label>
  </fieldset>
  <fieldset>
    <legend>Equipment interests: choose any</legend>
    <label><input type="checkbox" name="equipment" value="sensors"> Sensors</label>
    <label><input type="checkbox" name="equipment" value="motors"> Motors</label>
  </fieldset>
  <p><label for="idea">Project idea</label>
     <textarea id="idea" name="project_idea" rows="4"></textarea></p>
  <button type="submit">Request a place</button>
</form>

/workshop-booking is a placeholder endpoint. A server must implement it before this becomes a working service. Use fictional data for testing.

CHALLENGE 04 | TRACE

Predict what the form sends

Use 02.2 | Names and values

Read the markup below. Predict the submitted entries, including which values are omitted. Explain the roles of id, name and value. Assume the form is submitted successfully.

<input id="team" name="team_name" value="Comets">
<input id="note" value="We prefer mornings">
<input type="radio" name="session" value="build">
<input type="radio" name="session" value="code" checked>
<input type="checkbox" name="equipment" value="sensors" checked>
<input type="checkbox" name="equipment" value="motors" checked>
<input name="internal_reference" value="X7" disabled>

Success criteria

  • List each submitted name and value.
  • Include both checked equipment entries.
  • Omit the unnamed input, unchecked radio button and disabled control.
  • Explain why an id is not a replacement for name.
Need a hint?

Data is built from eligible controls. Repeated names can appear more than once; they are not automatically joined into one string.

Reveal a sample solution
team_name = Comets
session = code
equipment = sensors
equipment = motors

id identifies an element within the page. name is the submitted key. value supplies its value. The unnamed note and disabled reference are omitted.

CHALLENGE 05 | VALIDATE

Add rules and test their boundaries

Use 02.3 | Native validation

Improve the booking form. Require an email address, a whole-number participant count from 1 to 6 and a team code containing two capital letters followed by three digits.

Success criteria

  • Use suitable types, required, min, max, step and pattern.
  • Keep the expected format visible in a label or hint.
  • Associate hints using aria-describedby.
  • Test empty values, valid values and boundary cases.
  • Explain why the server would still need to validate a real request.
Need a hint?

For the participant count, test 0, 1, 6, 7 and 2.5. For the code, test AB123, ab123 and AB12.

Reveal a sample solution
<label for="email">Email address (required)</label>
<input type="email" id="email" name="email" required>

<label for="count">Participants (1 to 6, required)</label>
<input type="number" id="count" name="participants"
       min="1" max="6" step="1" required>

<label for="code">Team code (required)</label>
<p id="code-hint">Use two capital letters and three digits, for example AB123.</p>
<input type="text" id="code" name="team_code" required
       pattern="[A-Z]{2}[0-9]{3}" aria-describedby="code-hint">

Expected results: 1 and 6 pass the numeric rules; 0, 7 and 2.5 fail. AB123 passes the format rule; ab123 and AB12 fail. Required empty fields fail. Browser checks can be bypassed, so a real server must enforce the rules again.

These snippets replace or extend existing controls. Do not paste a second email control with the same id into the page.

CHALLENGE 06 | REPAIR

Make an error helpful and accessible

Use 02.3 | Labels, errors and keyboard access

Assume this snippet sits inside a form after an unsuccessful submission. Identify at least four problems and improve it. The Show help button should perform a separate action rather than submit the form.

<p>Enter your details.</p>
<input type="email" id="contact" name="email" placeholder="Email">
<button>Show help</button>
<p style="color:red;">Invalid!</p>

Success criteria

  • Add an associated visible label.
  • Give the help button type="button".
  • Explain what needs to be corrected in text.
  • Connect the hint and error to the field.
  • Use aria-invalid for an actual judged error state.
  • Preserve the user’s other values and keep focus visible.
Need a hint?

A placeholder is not a substitute for a label. aria-invalid communicates an error state but does not perform validation.

Reveal a sample solution
<label for="contact">Email address (required)</label>
<p id="contact-hint">Use an address such as alex@example.com.</p>
<input type="email" id="contact" name="email" required
       aria-invalid="true"
       aria-describedby="contact-hint contact-error">
<button type="button">Show help</button>
<p id="contact-error">Enter an email address in the form name@example.com.</p>

This represents an error state, not the initial untouched form. Custom code must show and clear the error and update aria-invalid when checks run. The help action needs its own programming. A custom error summary can link to the affected fields and receive focus after a failed submission.

CHALLENGE 07 | MEDIA

Publish a short demonstration with alternatives

Use 02.4 | Audio, video and embedded content

Add a short video explaining a project. Use a file you own or have permission to publish. Provide playback controls, suitable sizing, checked captions and a descriptive transcript.

Success criteria

  • The source path matches a supplied media file.
  • Use controls and avoid unexpected autoplay sound.
  • Keep the player proportional and within its container.
  • Attach a captions track and check its timing.
  • Include relevant visual information in narration or a descriptive alternative.
  • Provide a separate viewing link.
Need a hint?

Captions describe speech and meaningful sounds. A transcript can also describe important visual actions. The files referenced in sample code must actually exist.

Reveal a sample solution
<video controls preload="metadata" width="800" height="450"
       style="display:block;width:100%;max-width:800px;height:auto;margin:20px auto;">
  <source src="media/robot-demo.mp4" type="video/mp4">
  <track kind="captions" src="media/robot-demo-en.vtt"
         srclang="en" label="English" default>
</video>
<p><a href="media/robot-demo.mp4">Open the demonstration video</a></p>
<section>
  <h2>Demonstration transcript</h2>
  <p>The robot uses a sensor to detect the parcel.</p>
  <p>[The lifting arm raises the parcel onto its platform.]</p>
</section>
WEBVTT

00:00:00.000 --> 00:00:03.000
The robot uses a sensor to detect the parcel.

00:00:03.000 --> 00:00:06.000
[Motor starts]

Save the timed text as robot-demo-en.vtt and adjust it to the actual recording. Test through a local web server or hosted page because local-file restrictions can affect track loading.

CHALLENGE 08 | STRETCH

Build a complete workshop information page

Combine 02.1 to 02.4

Create workshop.html bringing the section together: a timetable, a booking-form interface and a short media explanation. Use your semantic HTML skills from section 01 to organise the page.

Success criteria

  • The document has a descriptive title, logical headings and semantic regions.
  • A caption and appropriate headers explain the timetable.
  • The form has clear labels, group legends, names and constraints.
  • Format hints remain visible and are associated with controls.
  • Media has usable controls and appropriate text alternatives.
  • Links, paths and validation boundaries have been tested.
  • The page works with a keyboard and remains readable at a narrow width.
  • The page clearly says the practice form does not make a real booking.
Need a hint?

Build one section at a time. Keep the form separate from the table and do not nest forms. Reuse tested components, then check the complete page for duplicate ids.

Reveal a sample solution

One possible page plan

  • header and nav: page name and links to timetable, booking practice and media sections.
  • main: introduction followed by a timetable section, a form section and a demonstration section.
  • footer: fictional workshop contact information and a reminder that the form is a practice interface.

There is no single correct finished page. For this challenge, keep submission as a demonstration and use fictional data. A live booking system requires implemented processing, server checks and appropriate handling of personal data.

Further stretch: plan an external player with a descriptive iframe title, a direct viewing link and an explanation of its third-party loading behaviour. Use the provider’s official embed URL rather than an ordinary watch-page URL.

REFLECT AND CONTINUE

Explain your decisions

Record one table design choice, one form improvement and one accessibility check. Explain which validation rules you tested and what a real server would still need to do.

Keep your HTML files and a screenshot. Next, use CSS to control the appearance of the structures you have built.