6. Forms

circle-info

Follow along with code examples herearrow-up-right!

Table of Contents:

Key Concepts

  • A form is a collection of inputs that can be filled out by a user to submit a collection of data.

  • Key form elements include <form>, <label>, <input>, <textarea>, <select>, <fieldset>, and <button>.

  • The <input> element's type attribute determines what kind of data the input accepts (e.g., text, number, date, checkbox, radio, email, url).

  • Labels and inputs connect using the for attribute on <label> and a matching id attribute on <input>. This connection is essential for accessibility.

  • The name attribute on inputs labels the data when the form is submitted.

  • The action attribute on <form> specifies the URL where form data gets sent.

  • The method attribute on <form> specifies how data is sent (typically "POST").

  • HTML validation attributes like required, min/max, minlength/maxlength, and pattern can validate form data before submission.

What is a Form?

A form is a collection of inputs that can be filled out by a user to submit a collection of data.

Q: What are some forms you've filled out recently? What data did they collect?

chevron-rightClick Here To See Some Exampleshashtag

Examples you might see:

  • Signing up for a website (username, email, password)

  • Applying for a job (name, resume, cover letter)

  • Making a purchase (shipping address, payment info)

  • Booking an event (date, number of attendees)

  • Leaving a review (rating, written feedback)

Today we'll build a Job Application Tracker — a form that helps you stay organized when applying to multiple companies. This is a tool you'll actually use during your job search.

A job application tracker form collecting company, position, and application details

When to Use a Form

Not every user interaction needs a form. Use a form when you're collecting multiple pieces of related data that will be submitted together.

Use a form when:

  • ✅ Registering a new user (name, email, password, preferences)

  • ✅ Recording a job application (company, position, date, status)

  • ✅ Paying for something by credit card (cardholder name, credit card number, expiration, zip code)

A form isn't necessary for:

  • ❌ A single search input that filters results as you type

  • ❌ A button that opens/closes a menu

  • ❌ A link that navigates to a new page

  • ❌ A single checkbox that toggles dark mode

Can you think of other examples?

chevron-rightQ: Which of these user interactions would require a form: (A) clicking on a "like" button on a social media post, (B) Searching for a flight, or (C) signing up for a gym membership.hashtag

(A) Clicking on a like button would not require a form since there is just one input to interact with: the button

(B) Searching for a flight and (C) signing up for a gym membership would both require forms since there are multiple pieces of information to submit.

Form Basic Structure

Every form follows a similar pattern:

  1. A form to contain the form elements

  2. A heading to describe the form

  3. Pairs of <label> and <input> elements for user input

  4. A submit <button> at the end.

Key parts:

  • <form>: Container for all inputs

  • <h2>: Heading that describes the form's purpose

  • <label>: Describes what each input is for

  • <input>: Where users enter data

  • <button>: Submits the form

TODO: Take 5 minutes to recreate this form structure in the body of your index.html file below the h1 element.

circle-info

Why do we wrap each label and input in divs?

<label> and <input> elements are both inline elements by default which can make the form look like one long line. By wrapping each pair in a <div>, we get each form input on a new line. It also makes it easier to style the pair as a unit.

Input Basics

Inputs are where users enter their data. The type attribute determines what kind of data the input accepts.

Each input type behaves differently — text accepts any characters, number only accepts digits, date shows a calendar picker, and so on.

TODO: Inside your form, add in three more <input> elements: (1) application date, (2) expected salary, (3) a job posting URL. For each, add a <label> describing the form input and surround the label/input pair with a <div>.

chevron-rightSolutionhashtag

We'll use a "date" type input for the application date, a "number" type input for the salary, and a "url" type input for the job posting url. Make sure to add a <label> for each <input> and wrap them in a <div>:

Labels

The <label> elements that we currently have are useful for our users with good eyesight. But for our visually impaired users, they aren't accessible.

To improve our form's accessibility we need to connect each <input> to its <label> using the id and for attributes:

How labels and inputs connect:

  • Give each <input> a unique id attribute

    • e.g. id="company-name"

  • Give each <label> a for attribute that matches the input's id

    • e.g. for="company-name"

  • The for and id values must match exactly.

Why this connection matters:

  • Screen readers announce the label when the input is focused, so users know what to enter

  • Clicking the label focuses its input — try it! This is especially helpful for small checkboxes since it makes the clickable area much larger.

  • The connection is semantic, not just visual — assistive technologies understand the relationship

chevron-rightQ: What happens when you click a label without the for attribute?hashtag

Nothing. The label is just text. The for attribute is what creates the connection to the input.

TODO: Add a for and matching id attribute to each pair of labels and inputs.

chevron-rightSolutionhashtag

At this point, your form should look like this:

Submit button

Technically, a form can be submitted without a submit button by pressing the Enter key. However, including a button to click on is an accessibility best practice.

Additionally, the type="submit" is actually optional (it's the default), but being explicit is good practice. A label isn't needed for this button as long as the text content is descriptive.

When a user clicks the submit button (or presses Enter), the browser collects all the form data and sends it somewhere. But where?

Form Submissions

In professional web applications, form data is typically sent to a server — a computer that receives the data and does something with it:

  • Store it in a database

  • Send an email notification

  • Process a payment

  • Create a user account

  • Update a record

Building your own server to handle form submissions requires learning backend technologies like APIs and databases like Postgres. We'll get there eventually! But for now, we can use a free service called Formspree that handles the server part for us.

Setting Up Formspree

Formspree receives your form submissions and forwards them to your email. Here's how to set it up for our Job Application Tracker:

1. Create a Formspree account

2. Create a new form

  • From your dashboard, click "New Form"

  • Give it a name like "Job Application Tracker"

  • Formspree will generate a unique form endpoint URL (the web address where the form data will be sent)

3. Update your HTML form

Add two attributes to your <form> element:

  • action — the Formspree endpoint URL where data gets sent

  • method="POST" — tells the browser to send data (rather than request it)

4. Add name attributes to your inputs

Formspree needs to know what to call each piece of data. The name attribute provides this label (use camelCase):

When Formspree receives this data, it will show up labeled as "companyName" and "positionTitle" in the email you receive. You can also view all of the form submissions on Formspree.

circle-exclamation

TODO: Update your form with the action and method attributes, and add name attributes to each input. Then test it by submitting some data and checking your email!

Input Deep Dive

Now that we know the basics of forms, let's look at a few additional types of inputs to make this form complete.

Textarea

A <textarea> element can be used for longer text inputs. The rows and cols attributes can set the initial size of the textarea and the placeholder attribute shows some placeholder text until we begin typing.

Let's add a textarea where we can take notes about the application.

TODO: Add the textarea input to your form.

Checkboxes

Checkboxes are useful when you need a yes/no answer to something.

It is common to see the label placed after the checkbox.

TODO: Add the checkbox input to your form.

Select

The <select> element creates a dropdown menu. It acts as a container for <option> elements which appear in the dropdown menu. Each option has a value attribute which defines how the selected option will show up in the dataset when the form is submitted.

TODO: Add the dropdown select input to your form.

Radios, Fieldset, and Legend

Radio inputs are useful if you want the user to choose one (and only one) option from a set of options. When all radio inputs share the same name attribute, selecting one radio option will deselect the others.

Each radio input has a value attribute which defines how the selected input will show up in the dataset when the form is submitted.

The <fieldset> and <legend> elements are used to group together a set of related input elements. They are particularly useful for radio elements which otherwise may look a bit untidy but can be used to group together any kind of input.

TODO: Add the fieldset and radio inputs to your form.

When To Use Each Input Type

  • type="text" — Any short, open-ended text

  • type="number" — Numeric data (can add min, max, step constraints)

  • type="date" — Dates (gives you a calendar picker)

  • type="email" / type="url" — Validates format automatically

  • <textarea> — Long, multi-line text

  • type="checkbox" — Yes/no, on/off (can select multiple if you have several)

  • type="radio" — Pick ONE from a few options (same name, different value)

  • <select> — Pick ONE from MANY options (use when you have 5+ choices)

Q: When would you use radio buttons vs. a select dropdown?

chevron-rightAnswerhashtag

Radio buttons when you have 2-5 options and want them all visible. Select dropdowns when you have many options (6+) and want to save space.

Note about radio buttons:

  • All radio buttons in a group must have the same name attribute

  • Each needs a different value attribute

  • The value is what gets submitted, not the label text

  • Use <fieldset> and <legend> to group related radio buttons (accessibility best practice)

Form Best Practices

HTML Form Validation

You can validate form data before it's submitted using HTML attributes:

Common validation attributes:

  • required — Field must be filled out

  • min / max — For numbers and dates

  • step — Specifies the interval between allowed values for numbers and dates

  • minlength / maxlength — For text

  • pattern — Must match a regex pattern

When validation fails, the browser shows an error message and prevents submission.

Q: Why is HTML validation helpful even though we'll add JavaScript validation later?

chevron-rightAnswerhashtag

- Provides instant feedback before JavaScript loads - Works even if JavaScript fails or is disabled - Accessible to screen readers - Less code to write (browser does the work)

Styling Forms

Forms need styling to be usable. Flexbox is particularly helpful for organizing form layouts.

Form container and basic styles:

Using flexbox for form fields:

Each label/input pair can use flexbox with flex-direction: column to stack vertically. The gap property adds space between the label and input:

Now, add the class="form-field" to each div container:

Two-column layouts with flexbox:

Use a .form-row wrapper to place two fields side-by-side. The flex: 1 on child .form-field elements distributes space equally:

Wrap two form fields in a div.form-row element to create a row with two columns:

Checkbox and radio layouts:

Checkboxes and radios look better with the label beside the input. Use flexbox with align-items: center:

Then set the class="radio-group" attribute on the fieldset and the class="radio-option" attribute on each radio div:

Responsive forms:

Use a media query to stack columns on small screens:

Key styling considerations:

  • box-sizing: border-box on all elements makes width calculations predictable

  • margin-inline: auto centers the form horizontally

  • gap in flexbox containers provides consistent spacing without margin hacks

  • flex: 1 distributes space equally among siblings

  • flex-direction: column in media queries converts rows to stacked layouts

Key Takeaways

  • Forms collect multiple related pieces of data that are submitted together

  • Always use labels for accessibility and usability

  • Different input types serve different purposes (text, number, date, select, etc.)

  • HTML validation provides instant feedback before JavaScript runs

  • Vertical layouts with full-width inputs work well for most forms

Next lesson, we'll use JavaScript to handle form submissions, extract data, and build interactive applications with that data.

Last updated