Today's craft
Forms, part 1 — the page finally listens.
Every page you've built so far talks — headings, lists, tables, all one-way. Today the direction reverses: forms are how a page asks the visitor a question and collects the answer. Every order you've placed, every login, every OTP box — all forms. By the end of this hour the Poshtik Campus order form is born.
Walk out of this room able to…
Idea one
Why forms exist.
Count today's taps: you logged in to the college portal (a form), maybe ordered breakfast (a form), searched something (a one-field form), entered an OTP (a form). The web without forms is a notice-board; the web with forms is every product you actually use. HTML gave pages this power with a small family of tags, and the head of that family is <form>.
The mental model for today: a form is an envelope. The inputs inside collect answers; the envelope's address says where those answers go; and the sending style says how they travel. Address and sending style have exact HTML names — that's the next idea.
Forms arrived in HTML 2.0 (1995) — before CSS, before JavaScript was everywhere, before "web app" was a phrase. The design was so right that a 1995 form still works in a 2026 browser unchanged. Everything fancier — React controlled inputs in Unit 3, API submissions in Unit 4 — is built on the exact element you meet today.
Idea two
<form>, action, method — the envelope, addressed.
Three words carry the whole structure. <form> is the envelope that wraps every question. action is where the answers are sent — an address on a server. method is how they travel — get (answers visible in the address bar, fine for searches) or post (answers carried privately in the request body, right for orders and logins).
<form> that already knows where its answers will go and how they'll travel — and see with your own eyes that an empty envelope draws nothing.- Create the
class-06folder in your sandbox, save asfirst-form.html· title text: Poshtik Campus — Order <h1>, then<form action="/place-order" method="post">holding only a comment
/place-order server doesn't exist yet; that's Unit 4's job.)<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8"> <title>Poshtik Campus — Order</title> </head> <body> <h1>Poshtik Campus — Order</h1> <form action="/place-order" method="post"> <!-- inputs will live here --> </form> </body></html>Poshtik Campus — Order
C:\Users\student\Desktop\fswd-practice\class-06\ — today's first file, so create the class-06 folder inside your sandbox first (right-click, New, Folder), same ritual as every class.first-form.htmlfswd-practice\ is your scratch sandbox — it is never a git repository. Commits happen only inside poshtik-campus\, the real project you put under git in Lab 1 — and we don't touch it today.Honesty flag (write it in your notes): the address /place-order points at a server we have not built yet. What actually receives form data is Unit 4's job — Express and Node. Today we learn to build and read the envelope; the post office opens in Unit 4. Nothing about the HTML changes then, which is exactly why learning it now is safe.
get appends answers to the URL — /search?dish=ragi — visible, bookmarkable, wrong for anything private. post carries answers inside the HTTP request body (remember Class 2's request anatomy?) — invisible in the URL, the default choice for orders, sign-ups and logins. Your exam may ask for exactly this one-line contrast.
Idea three
The two workhorses: type="text" and type="email".
One void tag — <input> — plays a dozen roles, and its type attribute picks the role. The two you'll type most for the rest of your life: text (any short answer) and email (an answer that must look like an address — the browser itself checks the shape).
- Save as
two-inputs.htmlinsideclass-06· title text: Two inputs - Inside the same
<form action="/place-order" method="post">: an<input type="text" name="student-name">and an<input type="email" name="student-email"> - Every input carries a
name— a nameless answer is never sent
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8"> <title>Two inputs</title> </head> <body> <form action="/place-order" method="post"> Your name: <input type="text" name="student-name"> College email: <input type="email" name="student-email"> </form> </body></html>C:\Users\student\Desktop\fswd-practice\class-06\ — the same folder you created for first-form.html; every file today lives there.two-inputs.htmlfswd-practice\ is scratch — git never watches it. Commits belong only to poshtik-campus\ (the repo you made in Lab 1), and that folder doesn't change today.The attribute that isn't optional: every input needs a name. When the form is sent, answers travel as name=value pairs — student-name=P. Ananya. An input without a name is a question whose answer gets thrown away: the browser simply doesn't send it.
Idea four
<label for> — the pairing that makes forms humane.
On the last slide the words "Your name:" were just loose text floating near a box — the browser had no idea they belonged together. <label> makes the bond official: its for attribute names the input's id, and the two become one unit.
<label> to its input so a click on the words lands the cursor in the box.- Save as
labelled.htmlinsideclass-06· title text: Labelled input <label for="student-name">Your name:</label>followed by an input whoseidmatches theforexactly — plus the usualname
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8"> <title>Labelled input</title> </head> <body> <form action="/place-order" method="post"> <label for="student-name">Your name:</label> <input type="text" id="student-name" name="student-name"> </form> </body></html>C:\Users\student\Desktop\fswd-practice\class-06\labelled.htmlfor/id pair is correct.poshtik-campus\ only.Why professionals never skip labels — three returns for one line: ① a bigger click target (labels are tap-friendly on phones); ② screen readers announce "Your name, edit text" instead of a nameless box — this is the accessibility habit from Class 3, applied to forms; ③ examiners award the mark for for/id matching. Match them exactly — for="student-name" pairs only with id="student-name".
Idea five
Three more types — and the exam question they carry.
type="date" gives a calendar picker. type="tel" raises the number keypad on phones. type="number" accepts only digits and grows little step arrows. Choosing the right type per question is exactly what your exam asks — and here is the actual past paper.
Q. Which input types would you use to accept a user's name, date of birth and email address? Write the HTML. [2M]
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8"> <title>Input types — exam answer</title> </head> <body> <form> <label for="name">Name:</label> <input type="text" id="name" name="name"><br> <label for="dob">Date of birth:</label> <input type="date" id="dob" name="dob"><br> <label for="email">Email:</label> <input type="email" id="email" name="email"> </form> </body></html>Beyond the marks: the exam pays for the middle column; a developer is really choosing the right column — every correct type is a contract the browser honours with free UI and free validation. Wrong type = silently lost behaviour: a DOB in type="text" still renders, but the calendar, the format guarantee and the mobile keypad all quietly vanish. “It looks the same” is not “it is the same” — the difference only shows when a user touches it.
name takes text · date of birth takes date · email takes email, each with a label = full 2 marks ✓ — diagram + depth past the marks, by course rule
C:\Users\student\Desktop\fswd-practice\class-06\pyq-input-types.html — yes, type the exam answer as a real file; a rendered answer is remembered ten times longer than a read one.The examiner wants to see three decisions, each visible: the type per field named in code, and labels attached. Don't write an essay; write the eight lines above and one sentence — "text for free-form names, date for a calendar-picked DOB, email for browser-validated addresses." Naming why each type fits is what separates a 2 from a 1.
The Poshtik order form begins.
This is a historic file: the first piece of the order form that will carry real orders by Unit 4. Below it stands with three holes. Fill all three, then type the whole file into your sandbox and check your render against the solution's preview — use exactly the text shown, so your page and the answer sheet must match character for character.
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8"> <title>Order from Poshtik Campus</title> </head> <body> <h1>Order from Poshtik Campus</h1>① open the form — answers go to /place-order, travelling privately <label for="student-name">Your name:</label>② the input for that label — free-form text, name and id both "student-name" <br><label for="student-email">College email:</label>③ the input for that label — the type that checks address shape, name and id both "student-email" </form> </body></html>SAMPLE OUTPUT — YOUR FINISHED FILE MUST RENDER EXACTLY THIS
Order from Poshtik Campus
Two labelled boxes under one heading — they LOOK identical, but the email box quietly rejects a non-address on submit, and pressing submit sends the answers privately (no ?name=… tail in the address bar). Those two invisible behaviours are exactly what your three missing lines must switch on.
Hint 1: "travelling privately" is one of the two values of method — the one that doesn't show answers in the address bar.
Hint 2: both missing inputs differ by exactly one word: the value of type. Everything else — id matching the label's for, plus a name — is the same discipline both times.
Answer sheet
The order form, complete.
Type your three guesses into the real file first — a wrong type that renders teaches more than a right answer that's read.
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8"> <title>Order from Poshtik Campus</title> </head> <body> <h1>Order from Poshtik Campus</h1> <form action="/place-order" method="post"> <label for="student-name">Your name:</label> <input type="text" id="student-name" name="student-name"> <br><label for="student-email">College email:</label> <input type="email" id="student-email" name="student-email"> </form> </body></html>Order from Poshtik Campus
C:\Users\student\Desktop\fswd-practice\class-06\order-form-start.html — the historic file: it walks out of Class 7 complete and becomes the model for Lab 2's real form in poshtik-campus\.poshtik-campus\ (Lab 2), that version gets git add + git commit — real project, real history.- Line 9: did you write both action="/place-order" and method="post"? "Travelling privately" was the clue for post — get would print the answers into the address bar.
- Lines 11 and 13: does each input's id exactly match its label's for? Click each label in your own render — if the cursor doesn't jump into the box, the pair is broken somewhere.
- Both inputs carry a name: without it the answer never leaves the page. Say the rule aloud once: label's for finds the input's id; the server reads the input's name.
Idea six
placeholder & required — hints and guard rails.
Two attributes finish today's vocabulary. placeholder shows grey ghost-text inside an empty box — a hint that vanishes on typing. required is a guard rail: the browser refuses to submit the form while that field is empty. No JavaScript, no server — the browser polices it alone.
- Save as
hints-and-rails.htmlinsideclass-06· title text: Hints and rails - One labelled text input carrying
placeholder="e.g. P. Ananya"ANDrequired, on top of the usualtype/id/name
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8"> <title>Hints and rails</title> </head> <body> <form action="/place-order" method="post"> <label for="student-name">Your name:</label> <input type="text" id="student-name" name="student-name" placeholder="e.g. P. Ananya" required> </form> </body></html>C:\Users\student\Desktop\fswd-practice\class-06\hints-and-rails.htmlForward flag, stated honestly: required is native HTML5 validation — shape-level checks the browser does free. Real validation logic ("is this roll number actually in our college?") needs JavaScript — that's Unit 2 — and server-side re-checking in Unit 4. Guard rails now, brains later.
The submit that refused.
A classmate types the file below, opens it, clicks Place order without typing anything — and the form doesn't submit. Instead a small message balloons out of the name box. Your job: from the code and the render, answer three questions before the solution:
- What blocked the submit?
- Is this an error the Console would show?
- Which single word in the code caused it?
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8"> <title>Blocked submit</title> </head> <body> <form action="/place-order" method="post"> <label for="student-name">Your name:</label> <input type="text" id="student-name" name="student-name" required> <button type="submit">Place order</button> </form> </body></html>C:\Users\student\Desktop\fswd-practice\class-06\blocked-submit.html — type it exactly as shown, including the required attribute; the "bug" is the lesson.Answer sheet
Reading the refusal correctly.
Write your three answers down first — especially the Console one. It's the trap.
- What blocked the submit? The browser's native HTML5 validation. Before sending any form, the browser checks every required field; the empty name box failed, so the browser cancelled the send and drew the bubble itself.
- Would the Console show an error? No — and this distinction is the whole lesson. Open DevTools and look: zero red lines. A validation bubble is not a JavaScript error; nothing crashed, nothing ran wrong. The Console reports code failures; this was the browser working exactly as designed. When JS arrives in Unit 2, you'll meet real Console errors — knowing which voice is speaking is a debugging superpower.
- The single word responsible: required on line 3. Delete it and the empty form submits happily — straight to a server that doesn't exist yet, but that's Unit 4's problem.
In your own file, collect the full set — three different bubbles, all free, all before a single line of JavaScript:
- Submit empty — "Please fill out this field."
- Change the input to type="email", type ananya, submit — "Please include an '@' in the email address."
- Add required to an email input and submit empty — the required message wins.
The input-type quick reference.
You met five types today. HTML5 ships more — none needs a lesson, all appear in real codebases and quiz options. Read once at home; recognition is the goal, not memorisation.
| TYPE | WHAT THE BROWSER GIVES YOU | USE IT FOR |
|---|---|---|
| text | Plain single-line box | Names, roll numbers, anything short and free-form |
| Address-shape check on submit; @ key on phone keyboards | Email addresses | |
| password | Typed characters masked as dots | Passwords — masking only; real security is server-side (Unit 4) |
| date | Calendar picker; value always YYYY-MM-DD | DOB, delivery dates |
| time | Clock picker | Pickup-time slots |
| tel | Number keypad on phones; no format check (world phone formats vary too much) | Phone numbers |
| number | Digits only, step arrows, min/max attributes | Quantities — "3 wraps" |
| range | A slider | Ratings, volume-style values |
| color | A colour-picker swatch | Theme choices |
| file | A Browse… button | Uploads — needs server support (Unit 4) |
| url | URL-shape check on submit | Website addresses |
| search | Text box with a clear-✕ on most browsers | Search bars |
| hidden | Renders nothing; still submits its name=value | Data the page knows but the user shouldn't edit |
| checkbox / radio | Tick square / choice dot | Class 7's whole story — tomorrow's class |
| submit / button | Clickable buttons | Sending — also properly told in Class 7 |
Every row is the same trade: tell the browser your intent (this is a date, this is a number) and the browser pays you back with a picker, a keypad, a check — for free. That is the semantics-over-styling principle from Class 3, now running your forms. The wrong habit — type="text" for everything — works, renders, and silently throws all those gifts away.
Wrap
What you can do now that you couldn't at 9 am.
The git rule, said once for the whole class: fswd-practice\ is scratch paper — no repo, no commits, throw files away freely. poshtik-campus\ is the real project you put under git in Lab 1 — every meaningful change there ends with git add . then git commit -m "…". Today we never opened it, so today needs zero commits. Lab 2 will change it — and that day, committing is not optional.
Homework — in your sandbox.
- Finish the file: extend order-form-start.html with two more labelled fields — Phone: as type="tel" (id and name student-phone) and Delivery date: as type="date" (id and name delivery-date). Make all four fields required.
- Collect the refusals: trigger all three validation bubbles from today's depth note and write each message down word-for-word.
- Exam rep: write the P2·Q2 answer once from memory on paper — eight lines, three types, timed at three minutes.
Next class the form learns to offer choices: radio buttons (and the name-collision bug that breaks them — a past exam question fixes it), checkboxes for protein add-ons, dropdowns, and the real submit button. The order form you started today walks out of Class 7 complete.