The HTML document
In short: An HTML document is text with tags and attributes from which the browser builds a tree of elements; semantic elements such as header, nav, main and footer say what each part is.
Problem
The price is a link
A colleague made the page of a product. You open it and the price is blue and underlined, and a click on "Add to cart" takes you to other breads. The code has no link around the price.
Console
The browser shows no error and the console is empty. Press "Add to cart": the console says that this is a link to /bread. The mistake is on line 9: the <a> is opened but never closed. The browser does not show the text line by line. It first builds something else from it, and that something is why the price is a link.
The idea
Elements, tags, attributes
HTML is text that says what is on the page. Every piece is an element: a heading, a paragraph, a link, a button. An element starts with an opening tag and ends with a closing one:
<a href="/cart">Cart</a><a …>is the opening tag, and</a>is the closing one: the same name with a/.href="/cart"is an attribute: a name and a value in the opening tag. It says something about the element: here, where the link goes.- "Cart" is the content: the text between the two tags.
Elements sit inside each other. A paragraph <p> can hold a link, and <body> holds everything you see. Some elements have no content and so no closing tag: <meta>, <img>, <input>, <br>.
The whole document always has the same frame:
<!doctype html><html lang="en"> <head> <meta charset="utf-8"> <title>Dobrudzha bread</title> </head> <body> … </body></html><!doctype html> says that this is modern HTML. lang="en" gives the language: a screen reader picks its voice by it, and the browser breaks words by it. <head> holds information about the page: the encoding and the title in the browser tab. <body> holds what you see.
The idea
From text to a tree
The browser does not draw the text. It reads it with a parser and builds a tree: every element is a node, and the elements inside it are its children. Every element has exactly one parent. This tree is called the DOM (Document Object Model). CSS and JavaScript work with it, not with the text.
The parser keeps track of which elements are open right now. An opening tag makes a new node, a child of the last open element. A closing tag closes the element, and the parser goes back to the parent.
If a closing tag is missing, the parser does not stop. HTML has a rule for every mistake, and the browser decides by itself where to close. Sometimes it decides differently from what you had in mind.
See it
See the tree being built
The code is the problem from the start, made short. Watch which elements are open on the right.
<body> <h1>Bread</h1> <p>See the <a href="/bread">other breads</p> <p>Price: €1.80</p> <button>Add</button></body>Step by step, in words
- The parser reads the code from the top. <body> opens an element: here it is the root of the tree. On the right are the elements that are open right now.
- <h1> becomes a child of the open element, <body>. </h1> closes it on the same line, and the parser goes back to <body>.
- <p> is a child of <body>, and <a> is a child of <p>. Now three elements are open: body, p, a.
- There is no </a>. </p> closes the paragraph, and <a> cannot stay outside it, so it is closed too. But the parser keeps it in mind: the link was never closed in the code.
- Before the next content the parser opens the kept <a> again, now as a child of <body>. This link is not in the code. The new <p> goes inside it.
- The button goes inside the link too.
- The path from the button up: button, a, body. The price and the button are inside a link, and a click on them leads to /bread. The fix is one </a> on line 3.
The second <a> is not in the code, but it is in the tree. The browser shows the tree, not the text. So when a page looks strange, you look at the tree: in the browser this is the Elements panel of the developer tools (F12). The second <a> is there, and the source (View Source) does not have it.
Try it
Fix the link
Fix the code so that the page has exactly one link: "other breads". Press "Check": the check counts the links on the page.
Console
Solution
index.html<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Dobrudzha bread</title>
</head>
<body>
<h1>Dobrudzha bread</h1>
<p>See the <a href="/bread">other breads</a></p>
<p>Price: €1.80</p>
<button type="button">Add to cart</button>
</body>
</html>
The </a> on line 9 was missing. With it the link ends before </p>, and the parser has nothing to open again. The price and the button are children of <body> again.
Try it
Find the bug
Why is "Delivery in 2 working days" bold?
Pick the line with the bug.
The <strong> on line 3 is not closed. </p> closes it together with the paragraph, but the parser keeps it in mind and opens it again around the next paragraph. It should be <strong>€1.80</strong></p>.
Try it
Fill in
Which attribute says where the link goes?
<nav>
<a ="/cart">Cart</a>
</nav>href (hypertext reference): the address the link goes to.
The idea
Elements with meaning
A page can be made only of <div> elements. Then the browser knows that there are boxes, but not what each one is. A person sees the menu by its place and its look. A screen reader, a search engine and the keyboard see only the tree.
So HTML has semantic elements: elements whose name says what the content is.
<header>: the top of the page: the logo and the menu.<nav>: the navigation, the group of links to the other pages.<main>: the main content. One per page.<article>: something whole that makes sense on its own: a product, an order, a post.<footer>: the bottom of the page: delivery, contacts, terms.<h1>…<h6>: the headings.<h1>is the heading of the page.
They look like a <div>. The difference is that a screen reader announces "navigation" and "main", and a keyboard user jumps to them with one key. <div> and <span> stay for boxes with no meaning: a group that CSS has to lay out.
See it
The page with meaning
The same product with semantic elements. The second file has a little CSS so that the parts are visible. The next module is about it.
Console
The check of the example finds the parts by role: <header> is "banner", <nav> is "navigation", <main> is "main", <footer> is "contentinfo". A screen reader sees them the same way.
Try it
Give it meaning
The page is made only of <div> elements. Replace them with semantic elements: the top, the menu, the main content, the product and the bottom. The name of the product is the heading of the page.
Console
Solution
index.html<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Fresh milk 3% · The shop</title>
</head>
<body>
<header>
<a href="/">The shop</a>
<nav>
<a href="/bread">Bread</a>
<a href="/milk">Milk</a>
<a href="/cart">Cart</a>
</nav>
</header>
<main>
<article>
<h1>Fresh milk 3%</h1>
<p>Price: €2.40</p>
<button type="button">Add to cart</button>
</article>
</main>
<footer>Delivery in 2 working days</footer>
</body>
</html>
top becomes <header>, menu becomes <nav>, content becomes <main>, product becomes <article>, and bottom becomes <footer>. The name of the product becomes <h1>: it is the heading of the page. The check looks for the button inside the article, for the menu by the role "navigation" and for the heading by level 1. The classes are no longer needed.
More precisely, if you are curious
The parser and mistakes. The rules for mistakes are part of the standard (the HTML Living Standard), so all browsers build the same tree from the same broken HTML. The parser keeps unclosed <a>, <strong>, <em>, <b> and <i> in a list (the list of active formatting elements) and opens them again. That is why such a mistake "spills" down the page.
Closed by itself. Some tags close others without a mistake: <p> closes an open <p>, and <li> closes an open <li>. So <li>Bread<li>Milk is two list items. We write the closing tags because then the code says the same as the tree.
Attributes. The names of tags and attributes do not depend on upper and lower case (<A HREF> is <a href>), but we write lower case. Some attributes have no value: <input required>. The quotes around a value can be left out, but they are safer.
<section> and <aside>. <section> is a part with a heading, a piece of something bigger. <aside> is content to the side of the main one: related products, an ad.
Exercise
My order
Make the page of order 1042 from scratch. At the top: a link "The shop" and a menu with two links: "My orders" and "Cart". The main content: the heading "Order 1042", the status "shipped" and two products, each with its name as a second-level heading and the quantity with the price under it (bread: 2 × €1.80, milk: 1 × €2.40), then "Total: €6.00". At the bottom: "Returns within 14 days of delivery".
Console
Solution
index.html<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Order 1042 · The shop</title>
</head>
<body>
<header>
<a href="/">The shop</a>
<nav>
<a href="/orders">My orders</a>
<a href="/cart">Cart</a>
</nav>
</header>
<main>
<h1>Order 1042</h1>
<p>Status: <strong>shipped</strong></p>
<article>
<h2>Dobrudzha bread</h2>
<p>2 × €1.80</p>
</article>
<article>
<h2>Fresh milk 3%</h2>
<p>1 × €2.40</p>
</article>
<p>Total: <strong>€6.00</strong></p>
</main>
<footer>Returns within 14 days of delivery</footer>
</body>
</html>
Every product is an <article> with its own <h2> heading: it is whole on its own. The heading of the page is one, <h1>. The total is a paragraph in <main>, and the returns rule is in the <footer>. The check looks by role and by heading level, so a <div class="title"> does not pass, however much it looks like a heading.
Test
Test yourself
Related lessons
Section titled "Related lessons"- Continues in: Text, links, images, tables · Forms · Accessibility · Selectors and the cascade
- Tasks on this topic: HTML: the structure of a page