Reading HTML
structure, semantics, attributes
What it is
HTML is not a programming language but markup: it describes what a page is made of. Reading it is easy, and for working with an AI that is enough: you have to understand what structure it proposed and be able to say what you want instead.
What it looks like in code
<article class="card" data-city="oslo">
<h2 class="card__title">Oslo</h2>
<p class="card__temp">Currently <strong>+4</strong></p>
<button type="button" aria-label="Remove subscription">×</button>
</article>How to read it
A tag opens and closes: <p> … </p>. Some need no closing:
<img>, <input>, <br>.
Nesting = structure. <strong> inside <p> inside <article> — a
tree, the DOM from article 8.1. Indentation in the code affects nothing;
only the nesting matters.
Attributes are name="value" pairs in the opening tag:
| Attribute | What for |
|---|---|
class | a hook for CSS and JS; many elements can share one |
id | a unique name; there should be one per page |
data-* | your own data: data-city="oslo" can be read from JS |
type, href, src | meaningful ones, depending on the tag |
aria-* | hints for screen readers |
Semantics
Tags differ not in appearance but in meaning. <div> means nothing;
<article>, <nav>, <header>, <button> do.
The difference is practical, not aesthetic:
<div class="btn" onclick="remove()">×</div> <!-- don't do this -->
<button type="button" onclick="remove()">×</button>A <button> is reachable from the keyboard by itself, activates on space
and Enter by itself, and tells screen readers by itself that it is a
button. A <div> does none of that — all of it has to be added by hand,
and usually gets forgotten.
The reading rule: when you see a <div> with a click handler, there
should almost always be a <button> or an <a> there.
Forms
<form>
<label for="city">City</label>
<input id="city" name="city" type="text" required minlength="2">
<button type="submit">Subscribe</button>
</form>Three things to check in forms:
- The
labelis tied to the field byfor=id. Without it, clicking the label doesn't put the cursor in the field. name— the value travels to the server under this name. Nonameand the field isn't sent at all.required,minlength,type="email"— validation on the browser side. Convenient for the user, and no substitute for validation on the server (article 7.3): a request can be sent bypassing the form.
The document's structure
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Weather</title>
<link rel="stylesheet" href="/style.css">
</head>
<body>
…
<script src="/app.js"></script>
</body>
</html><head> is housekeeping, invisible on the page. <body> is what is
visible. lang="en" affects hyphenation and how screen readers pronounce
things, and viewport affects how the page looks on a phone. Without it a
mobile browser shows a shrunken desktop version.
What to tell the AI
Rewrite this markup semantically: divs with handlers become
buttons, navigation blocks become nav, headings by level.
Don't touch the classes or the styles.Check the form: does every field have a name and a linked
label, are the basic constraints there? A list of problems,
no edits.I want a city card: name, temperature, remove button.
Propose the markup — semantic, with BEM-style classes.
No styles needed yet.What to look for
A <div> instead of a button or a link. The most common problem in
generated markup.
No alt on images. <img src="..." alt=""> — an empty alt is fine
for decorative images, a missing one is not.
Headings out of order. <h1> then straight to <h4> — the document's
structure breaks for anyone reading it with a program.
Styles inline in the markup. style="margin-top: 10px" on every
element means changing it later in twenty places.
A repeated id. It must be unique; duplicates break CSS, JS, and the
label-to-field link.
Markup five <div> levels deep. A sign the AI built the structure
around the appearance rather than the meaning.
Cheat sheet
Nesting is the structure; indentation affects nothing.
classfor many,idfor one,data-*for your own data.A
<div>with a click handler should almost always be a<button>.In a form check:
name, a linkedlabel, constraints.Browser validation does not replace server validation.
viewportin the<head>, or the page shrinks on a phone.