HTML — Fundamentals
Document structure — the skeleton every page needs
Every HTML page starts from the same skeleton. Think of it like a building permit's required minimum — the doctype, html, head, and body aren't optional decoration, they're what tells the browser "this is a real, standards-mode HTML page" rather than something to guess at.
tells the browser to render in standards mode (not a legacy "quirks mode" that reinterprets old, inconsistent browser behavior).lang="en" matters more than it looks — screen readers use it to select the correct pronunciation, and it's a real accessibility requirement, not decoration. must come first inside (within the first 1024 bytes) — it tells the browser how to decode the byte stream into actual characters, and getting it wrong shows up as garbled text (mojibake) for any non-ASCII character. tells mobile browsers to render at the device's actual width instead of pretending to be a 980px-wide desktop page and zooming out — without it, a mobile-responsive CSS layout simply won't kick in correctly.Semantic layout elements — giving regions actual meaning
Before semantic elements existed, every page was built from generic A useful mental model: Never skip a level for visual reasons ( A form's The Always set Build a single page with class="header" — visually fine, but meaningless to a screen reader or search engine, which sees an undifferentiated wall of divs. Semantic elements fix this by naming the role of a region, not just its appearance.main is "the actual reason this page exists" (there should be exactly one per page); article is content that would make sense standalone if syndicated elsewhere (a blog post, a product card); section groups related content under its own heading; aside is tangential — related but not essential to the primary content, like a sidebar of related links.Headings — a hierarchy, not a font-size picker
through describe a document's outline — screen reader users frequently navigate a page by jumping heading-to-heading, the same way a sighted user might skim a table of contents. Choosing a heading level because "it looks the right size" instead of because it's genuinely a subsection of the heading above it breaks that navigation.h1 straight to h4 because the h4 styling "looks right") — style the element with CSS to look however you want; the heading level should always reflect actual document structure, not desired appearance.Forms — the elements that actually collect data
name attribute (not id) is what gets sent to the server on submit — a very common beginner bug is a form field with an id but no name, which submits nothing for that field. / pairing does real work, not just visual proximity — clicking the label text focuses the input (helpful for anyone with limited motor precision, including on mobile), and a screen reader announces the label when the input receives focus. A with no for/id connection is just floating text as far as assistive technology is concerned, even if it's positioned right next to the field visually.type="email" isn't just semantic — it triggers real built-in browser validation and, on mobile, a keyboard layout with @ and . easily accessible. Using type="text" for an email field throws that away for no benefit.Tables — for tabular data, and only tabular data
scope="col" tells a screen reader that this header applies to the entire column below it — without it, a screen reader user navigating cell-by-cell has no announced context for what each value means. Reaching for purely to lay out a page (a habit from before CSS layout existed) is a real anti-pattern: a screen reader announces "table, 3 columns, 5 rows" for something that isn't actually tabular data at all, which is actively confusing rather than neutral.
Images and media — responsive and accessible by default
width/height (even if CSS later overrides the display size) — the browser reserves the correct amount of space before the image finishes loading, which prevents the page from visibly jumping around as images load in (a real, measurable metric called Cumulative Layout Shift).Try it
header → main (containing one article with a real heading hierarchy and a form with two properly-labeled fields) → footer. Then open DevTools' Elements panel and confirm the tree structure you see matches exactly what you wrote — that confirms you understand the relationship between your HTML source and the live DOM the browser actually builds from it.

