6. Forms
Follow along with code examples here!
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'stypeattribute determines what kind of data the input accepts (e.g.,text,number,date,checkbox,radio,email,url).Labels and inputs connect using the
forattribute on<label>and a matchingidattribute on<input>. This connection is essential for accessibility.The
nameattribute on inputs labels the data when the form is submitted.The
actionattribute on<form>specifies the URL where form data gets sent.The
methodattribute on<form>specifies how data is sent (typically"POST").HTML validation attributes like
required,min/max,minlength/maxlength, andpatterncan 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?
Click Here To See Some Examples
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.

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?
Q: 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.
(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:
A
formto contain the form elementsA heading to describe the form
Pairs of
<label>and<input>elements for user inputA 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.
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>.
Solution
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 uniqueidattributee.g.
id="company-name"
Give each
<label>aforattribute that matches the input'side.g.
for="company-name"
The
forandidvalues 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
Q: What happens when you click a label without the for attribute?
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.
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
Go to formspree.io and sign up with your email (it's free)
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 sentmethod="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.
Every input needs a name attribute for the data to be submitted. Without it, that input's data won't be included in the submission.
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 texttype="number"— Numeric data (can addmin,max,stepconstraints)type="date"— Dates (gives you a calendar picker)type="email"/type="url"— Validates format automatically<textarea>— Long, multi-line texttype="checkbox"— Yes/no, on/off (can select multiple if you have several)type="radio"— Pick ONE from a few options (samename, differentvalue)<select>— Pick ONE from MANY options (use when you have 5+ choices)
Q: When would you use radio buttons vs. a select dropdown?
Answer
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
nameattributeEach needs a different
valueattributeThe
valueis what gets submitted, not the label textUse
<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 outmin/max— For numbers and datesstep— Specifies the interval between allowed values for numbers and datesminlength/maxlength— For textpattern— 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?
Answer
- 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-boxon all elements makes width calculations predictablemargin-inline: autocenters the form horizontallygapin flexbox containers provides consistent spacing without margin hacksflex: 1distributes space equally among siblingsflex-direction: columnin 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