Why this session exists
HTML is the least intimidating language in tech: no installation, no compiler, no math - a text file and a browser, both already on your machine. Over six sessions you build one real thing: your own page on the internet, "your corner of the internet", live on a real URL by Session 6. Today it is born: a file called index.html with your name in it.
index.html about you, open in your browser. The orange code panels below are live: edit the left side, the right side re-renders. Break things freely - Reset brings the original back.
Elements - the whole language in one idea 7 min live
HTML has one move: wrap content in tags to say what it IS. A heading, a paragraph, a link, an image. Learn the anatomy of one element and you have learned the grammar of all of them.
LiveTags wrap meaning around text3 min▶
Take the sentence "My cat is very grumpy". Wrap it in <p> tags and the browser knows it is a paragraph. Wrap a word in <strong> and the browser knows it matters. That is the entire job: HTML marks up what things ARE, and everything else (looks, behavior) builds on that truth.
<h1>My first heading</h1> <p>My cat is <strong>very</strong> grumpy.</p>
Why this matters to you
- Meaning is machine-readable. Search engines, screen readers, and AI assistants all navigate pages by these tags - good markup is how your page gets understood, not just seen.
- The browser is forgiving but literal. It renders exactly what the tags claim. Claim a heading with
<h1>and you get one; fake it with big bold text and machines see nothing.
Every Claude artifact, every dashboard export, every email template you have ever received is this exact grammar. A data person who reads HTML can inspect any web page, fix any report template, and hand-tune any AI-generated artifact instead of regenerating and praying.
LiveAttributes - settings on the opening tag2 min▶
Attributes are name="value" pairs that live in the opening tag and configure the element: where a link goes (href), which file an image shows (src), what a screen reader says about it (alt). Rules: space before the attribute, value in quotes, never inside the content.
<p>My favorite reference is <a href="https://developer.mozilla.org">MDN</a>. </p>
href="page.html". Unquoted values work until a space or special character breaks them silently - quoting is the seatbelt.
LiveNesting - boxes inside boxes, never overlapping2 min▶
Elements go inside other elements - a <strong> inside a <p> inside the page. The one law: close inner elements before outer ones. <p><strong>text</strong></p> is nested; <p><strong>text</p></strong> is overlapped, and the browser has to guess what you meant.
- Indent nested elements two spaces - the browser doesn't care, the next human (you, next month) does.
- Void elements have no content and no closing tag:
<img>,<br>,<hr>,<meta>. They are settings-only elements - all attributes, no text.
Self-studyBlock vs inline - the two behaviors2 min read▶
Every element has one of two default behaviors, and knowing which is which explains most "why is it on a new line?" surprises:
- Block elements claim a full row and stack downward:
<h1>-<h6>,<p>,<ul>,<div>, and the structural elements from Session 3. - Inline elements flow inside a line of text without breaking it:
<strong>,<em>,<a>,<code>,<span>.
<h2>A block claims the row</h2> <p>But <strong>inline</strong> elements like <em>emphasis</em> and <code>code</code> flow inside the text.</p>
One consequence worth knowing early: nesting a block inside an inline (a <div> inside an <a>'s text) is usually a smell. Blocks hold inlines, not the reverse.
The skeleton every page wears 7 min live
View the source of any site on earth - your bank, a newspaper, this page - and the same five-line skeleton stares back. Learn it once, recognize it everywhere.
LiveThe five lines, one by one3 min▶
<!DOCTYPE html>- a historical handshake that now just means "render this in modern standards mode". Always line 1, exactly like this.<html lang="en">- the root element wrapping everything. Thelangattribute tells screen readers which voice to use and translators which language they're leaving.<head>- metadata: the browser-tab title, character encoding, favicon, CSS. Visitors never see the head directly.<body>- everything visible. All of today's work after this line.<meta charset="utf-8">- first line inside the head. Declares the character encoding so names, accents, emoji and every non-English character survive. Skip it and "Phoebe's café" can render as garbage.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>This shows in the browser tab</title>
</head>
<body>
<h1>This shows on the page</h1>
<p>The head is the label. The body is the box.</p>
</body>
</html>
Self-studyWhat browsers forgive (and why you shouldn't lean on it)2 min read▶
Browsers are heroically forgiving: forget a closing tag, skip the doctype, misspell an attribute - something still renders. That's a design choice from 1995 (never punish the reader for the author's mistakes), and it cuts both ways:
- Good: your learning pages never explode with error messages. Experimentation is safe.
- Bad: mistakes hide. The page "works" while the structure underneath is quietly wrong - until a style, a screen reader, or another edit exposes it.
The professional habit: don't rely on forgiveness. Session 6 introduces the W3C validator, which reads your file with zero mercy and lists every technical sin. Until then: close what you open, quote your attributes, nest cleanly.
A marketing team's email template rendered fine in Chrome for months - one unclosed <div>. Then Outlook, far less forgiving, showed half the email inside a button. Forgiveness is a browser feature, not a file property: write it right and it works everywhere.
Headings and paragraphs - structure readers feel 6 min live
Six heading levels and one paragraph tag carry most of the meaning on most pages. Used with discipline they give your page an outline that humans skim, screen readers jump through, and search engines rank with.
LiveThe heading ladder, used honestly3 min▶
<h1> to <h6> are an outline, not a font-size menu. Three rules cover professional use:
- One
<h1>per page - the page's own title. Everything else nests under it. - Never skip levels going down. h1 → h2 → h3. Jumping h1 → h4 because "it looks right" breaks the outline; size is a Session 5 problem.
- Headings label the section that follows - if nothing follows it, it wasn't a heading.
<h1>Phoebe Fu</h1> <p>Data and AI person. This page is my corner of the internet.</p> <h2>Projects</h2> <p>Things I have built and shipped.</p> <h2>Now</h2> <p>What I am learning this season.</p>
Screen-reader users routinely navigate by a headings list - h1 to h6 as a table of contents. A page with honest headings takes seconds to skim by ear; a page of bolded fake headings is an unbroken wall. The same outline is what search engines use to understand what your page covers.
LiveParagraphs, line breaks, and collapsing whitespace2 min▶
Each <p> is one thought. The browser adds the spacing between paragraphs - you never add blank lines for layout. And a surprise for every beginner: whitespace collapses. Ten spaces, five newlines - the browser renders one space.
<p>This sentence has wild spacing in the source.</p> <p>New thought? New paragraph element.</p>
<br>forces a line break INSIDE a paragraph - for poems and addresses, not for spacing between blocks.<hr>draws a thematic break - a scene change between paragraphs.
Self-studyComments - notes the browser skips1 min read▶
Anything between <!-- and --> is invisible to visitors: <!-- TODO: add photo here -->. Use comments to leave notes for future-you, to label sections of a long file, or to temporarily hide an element while testing ("comment it out"). One caution: comments are visible to anyone who views source - no secrets in them.
Birth of index.html ★ 8 min · follow along
Your corner of the internet starts as one file in one folder. We create it with a real editor, write the skeleton from memory, and open it in the browser - the moment the file becomes a page.
Get a real text editor if you don't have one - VS Code is free and what we'll reference. (TextEdit and Word secretly reformat files; they are the one wrong tool for this job.)
Make a folder called my-site somewhere you'll find it again. Inside it, create a new file named exactly index.html - lowercase, no spaces. That name is special: it's the page servers show by default.
Type the skeleton from memory - doctype, html with lang, head with meta charset and a <title>Your Name</title>, empty body. Typing it builds the muscle; pasting doesn't.
In the body: an <h1> with your name, and one honest <p> about who you are. Save.
Open the file in your browser - double-click it, or drag it onto the browser window. Your name, in a page you built. Check the browser tab: there's your title.
The loop you'll use forever: edit in the editor → save → reload the browser tab. Change your h1, save, reload. That 3-second loop is web development.
.html (not .html.txt - turn on file extensions in your file manager), and that you saved before reloading. Those two cover 90% of first-page confusion.
Outline your page like a pro ★ 5 min · build your own
Before writing content, professionals write the outline. Give your page its heading ladder now - the sections will be filled across the next five sessions.
Under your h1 and intro paragraph, add three <h2> sections: About, Projects (or Interests), and Contact.
Give each h2 one placeholder paragraph - a single honest sentence about what will live there.
Under Projects, practice level 3: two <h3> entries for real things you've made or want to make, each with a one-line <p>.
Add one comment to future-you: <!-- Session 3: photo goes here -->. Save, reload, admire the outline.
This h1 → h2 → h3 discipline is the same outline discipline as a good doc or a good deck. People who write clean HTML outlines tend to write clean documents - it's one skill wearing two outfits.
Break it on purpose ★ 4 min · build your own
The fastest way to lose fear of a language: break it deliberately and watch how it fails. HTML fails gently - see it once and error messages never scare you again.
In any playground above (or your own file): delete a closing </strong>. Watch the bold leak forward - the browser guessed where it ends, and guessed wrong.
Overlap two elements: <p><strong>text</p></strong>. Still renders! The browser silently rewrote your structure - forgiveness hiding a mistake.
Break an attribute: remove the quotes from an href with a space in it. The link now goes somewhere strange - the unquoted value ended at the space.
Fix all three (or hit Reset). Diagnosis habit acquired: when a page looks weird, suspect an unclosed tag or unquoted attribute first.
Try it yourself - this week ◐ 30-45 min total
- Finish your outline: every h2 section gets 2-3 real paragraphs. Write like you talk - the markup matters this week, not the prose.
- View source on three sites you use daily. Find the doctype, title, and first h1 of each. Notice how much you can now read.
- Rebuild the skeleton from memory in a fresh file, twice. Under 60 seconds each means it's yours forever.
- The whitespace experiment: put 10 blank lines between two sentences in one paragraph, reload, watch them collapse. Now you'll never fight the browser with spaces.
- Bring to Session 2: one page (yours or anyone's) whose heading structure feels messy - we dissect one together before links and lists.
Official sources covered
This session teaches the working content of these lessons from MDN's Structuring content with HTML and web.dev Learn HTML. MDN's interactive challenges and web.dev's own quizzes stay with the originals - our exercises are equivalents, not copies.
Three questions before you go 🎯 ◐ 90 seconds
1 · Your h1 shows on the page but the browser tab is blank. What's missing?
The tab reads the head's title element; the h1 lives in the body. Head = about the page, body = on the page.
2 · You want more space between two paragraphs. The right move is...
Whitespace collapses and br-stacking is fake structure. HTML says what things are; CSS says how far apart they sit.
3 · Which snippet is correctly nested?
Boxes inside boxes: close the inner element before the outer one. B and C overlap - the browser will rewrite them silently.