HTML
The document itself: semantic structure, forms and native validation, media, and the metadata everything else reads.
Why HTML Comes First
HTML describes what something is, not what it looks like. A <button> is a button because of the tag, not because it is styled like one. That distinction is the whole subject: the tag you choose decides what the browser, assistive technology and search engines understand.
Get it right and a great deal comes free. A real <button> is already focusable, already fires on Enter and Space, already announces itself as a button, and already works before your JavaScript has loaded. A <div onclick> has none of that, and every attempt to add it back is a bug waiting to happen.
The document has a fixed shape: <!DOCTYPE html>, then <html lang="en">, then a <head> of metadata nobody sees and a <body> of content everybody does. The lang attribute is not decoration — screen readers pick a pronunciation from it.
Browsers never refuse to render broken HTML. They guess, silently, and their guesses differ from yours. That is why a validator is worth more here than in most languages: nothing else will tell you.
Semantic Elements
Semantic elements name the region they wrap. They produce the document outline a screen-reader user navigates by, the way a sighted reader skims headings.
| Element | Use it for | Notes |
|---|---|---|
<header> | Introductory content for the page or a section | More than one per page is fine |
<nav> | A block of navigation links | Label it if there are several |
<main> | The unique content of this page | Exactly one, and skip links target it |
<article> | Something that stands alone | A post, a card, a comment |
<section> | A thematic grouping | Needs a heading, or use a div |
<aside> | Tangential content | Sidebars, pull quotes |
<footer> | Closing content | Authorship, links, copyright |
Headings carry the outline. <h1> to <h6> must descend without gaps — an <h4> directly under an <h2> tells a screen reader a level is missing. Choose the level for its position in the document, never for its size; size is CSS.
Forms & Native Validation
Forms are where HTML gives away the most for free — and where hand-rolled replacements go wrong most often. Every input needs a <label> tied to it, because that label is both the accessible name and a bigger tap target.
<!-- the label's for= matches the input's id --> <label for="email">Work email</label> <input id="email" name="email" type="email" <!-- right keyboard on mobile, free format check --> autocomplete="email" required> <label for="pw">Password</label> <input id="pw" type="password" minlength="12" required> <button>Create account</button> <!-- submits by default -->
The type attribute is the highest-value character in a form. email, tel, url, number, date and search each change the mobile keyboard, and several bring validation with them. autocomplete lets a password manager fill the field correctly, which measurably raises completion.
| Attribute | What it enforces |
|---|---|
required | Cannot submit while empty |
minlength / maxlength | Character bounds on text |
min / max / step | Numeric and date bounds |
pattern | A regular expression the value must match |
Images, Video & Responsive Media
Images are usually the heaviest thing on a page, so the markup decisions here move your performance numbers more than most code will.
Always set width and height. The browser uses the ratio to reserve space before the file arrives, which stops the page jumping as images load — the single largest cause of a poor layout-shift score.
<img src="photo-800.jpg" srcset="photo-400.jpg 400w, photo-800.jpg 800w, photo-1600.jpg 1600w" sizes="(max-width: 700px) 100vw, 700px" width="800" height="600" loading="lazy" alt="A harbour at dawn, boats still moored">
srcset offers the browser several files and sizes tells it how wide the image will actually be laid out, so it can choose before layout happens. loading="lazy" defers anything below the fold — but never put it on the image at the top, which is usually the one being measured.
Alt text follows one rule: write what the image tells the reader, not what the picture contains. If it is purely decorative use alt="", which tells a screen reader to skip it entirely. Omitting alt altogether is the worst option — the file name gets read aloud instead.
Metadata & SEO Basics
The <head> is what everything except the reader consumes: search engines, social cards, the browser tab, and the phone deciding whether your page can be installed.
<meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <title>Harbour at Dawn — Field Notes</title> <meta name="description" content="What the page is about, in one sentence."> <link rel="canonical" href="https://example.com/harbour"> <!-- the social card --> <meta property="og:title" content="Harbour at Dawn"> <meta property="og:image" content="https://example.com/card.png">
Without the viewport tag a phone pretends to be a desktop and shrinks everything — none of your responsive CSS will apply. canonical tells search engines which URL is the real one when the same content is reachable several ways, which is how duplicate-content penalties are avoided.
Common Mistakes
| Mistake | Why it hurts | Instead |
|---|---|---|
<div onclick> as a button | Not focusable, no keyboard, not announced | <button> |
| Heading level chosen for size | Breaks the outline people navigate by | Pick by position, size with CSS |
Missing alt | The file name is read aloud | Describe it, or alt="" if decorative |
| Placeholder used as a label | Vanishes on typing, poor contrast | A real <label> |
No width/height on images | Page jumps as images load | Always set both |
Several <h1>, or none | No clear page title in the outline | One per page |
Interview Questions
Why prefer a <button> over a styled <div>?
The button is focusable, activates on Enter and Space, is announced as a button, participates in form submission, and works before JavaScript loads. Reproducing all of that on a div takes a tabindex, a role, two key handlers and still misses cases.
What does the viewport meta tag actually do?
It tells a mobile browser to lay out at the device width rather than pretending to be a roughly 980px desktop and scaling down. Without it your media queries never match and everything renders tiny.
srcset versus sizes — what is the difference?
srcset lists the files available and how wide each one is. sizes tells the browser how wide the image will be once laid out. It needs both to choose correctly before layout has happened.
When should alt be empty?
When the image adds nothing a reader would miss — decoration, a spacer, an icon beside text that already says the same thing. Empty alt makes a screen reader skip it. Omitting alt entirely is different, and worse.
Is client-side validation enough?
No. It is a convenience for the person filling in the form. Anything can post to your endpoint directly, so the server has to validate regardless.