Lesson 2 of 17 · HTML and CSS
HTML: page structure, semantic tags, links and images
Objective
Write by hand an HTML page that is valid and well structured: the mandatory skeleton, headings and paragraphs, lists, the main semantic areas (header, nav, main, footer), links and images. At the end, you will have the home page and the "Nos chambres" (Our rooms) page of Riad Yasmine in Marrakech.
Key points
- HTML describes the content and its meaning ("this is a heading", "this is a menu"), not its appearance: appearance is the job of CSS.
- An element = opening tag + content + closing tag:
<p>Bonjour</p>. Attributes give details about the element:<a href="chambres.html">. - Every page starts with
<!doctype html>, then<html lang="fr">, a<head>(information about the page) and a<body>(what is displayed). - Semantic tags (
header,nav,main,article,section,aside,footer) help screen readers and search engines. - Only one
h1per page, thenh2,h3… in order, without skipping a level. - Every image has an
altattribute that describes what it shows.
1. Anatomy of an element
<a href="chambres.html" title="Voir les chambres">Nos chambres</a>
<!-- └ opening tag with two attributes ┘└ content ┘└ closing ┘ -->
- Attributes are written
name="value"in the opening tag, separated by spaces. - Elements nest like Russian dolls, and close in reverse order:
<p>Un <strong>prix</strong> imbattable</p>is correct,<p>Un <strong>prix</p></strong>is not. - Some elements are void (no content, no closing tag):
<img>,<br>,<meta>,<link>,<input>,<hr>. <!-- ... -->is a comment: visible in the source code, never on the screen.- HTML ignores multiple spaces and line breaks: indent your code for yourself, not for the browser.
2. The page skeleton
<!doctype html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="Riad de charme dans la médina de Marrakech, six chambres, patio et terrasse.">
<title>Riad Yasmine — Maison d'hôtes à Marrakech</title>
<link rel="stylesheet" href="style.css">
<link rel="icon" href="favicon.png">
</head>
<body>
<!-- everything that is displayed -->
</body>
</html>
| Line | Role |
|---|---|
<!doctype html> |
"this is modern HTML"; without it, the browser switches to compatibility (quirks) mode |
lang="fr" |
the page language: screen reader pronunciation, translation, search ranking. For a page in Arabic: lang="ar" dir="rtl" |
<meta charset="utf-8"> |
the encoding: without it, "Fès" and "مرحبا" show up as strange characters |
viewport |
essential for correct display on a phone (lesson 1.6) |
description |
the summary shown under the title in search results |
<title> |
the text of the tab and of the link in Google: precise and unique for each page |
<link rel="stylesheet"> |
links the CSS stylesheet |
The <head> is not displayed: it contains metadata, information about the page.
3. Headings, paragraphs, emphasis
<h1>Riad Yasmine</h1>
<p>Une maison d'hôtes de six chambres, à cinq minutes de la place Jemaa el-Fna.</p>
<h2>Le riad</h2>
<p>Construit au <strong>XVIIIᵉ siècle</strong>, entièrement restauré en 2023.</p>
<h2>Les services</h2>
<h3>Petit-déjeuner</h3>
<p>Msemen, baghrir, amlou et jus d'orange pressé, <em>servis sur la terrasse</em>.</p>
<h3>Hammam</h3>
<p>Sur réservation, la veille.</p>
h1toh6form the outline of the page. A screen reader lets you jump from heading to heading: this is their real purpose. Never choose a heading for its size (size is set in CSS).<p>: a paragraph. For a simple line break in an address, use<br>; to separate ideas, use a new<p>.<strong>: importance (bold by default);<em>: emphasis (italic). These are meaning tags;<b>and<i>only carry a style.
4. Lists
<ul> <!-- bulleted list: the order does not matter -->
<li>Wi-Fi gratuit</li>
<li>Terrasse avec vue sur l'Atlas</li>
<li>Navette depuis l'aéroport Marrakech-Ménara</li>
</ul>
<ol> <!-- numbered list: the order matters -->
<li>Choisissez vos dates</li>
<li>Choisissez votre chambre</li>
<li>Confirmez par e-mail</li>
</ol>
<dl> <!-- description list: term / description -->
<dt>Arrivée</dt><dd>à partir de 14 h</dd>
<dt>Départ</dt><dd>avant 11 h</dd>
</dl>
A navigation menu is basically a list of links: many sites write it as <nav><ul><li><a …></a></li>…</ul></nav>.
5. Semantic structure tags
Before HTML5, everything was made of anonymous <div> elements. Today, we name the areas:
<body>
<header> <!-- site header: logo, name, menu -->
<h1>Riad Yasmine</h1>
<nav> <!-- main navigation menu -->
<a href="index.html">Accueil</a>
<a href="chambres.html">Chambres</a>
<a href="#contact">Contact</a>
</nav>
</header>
<main> <!-- THE main content (only one per page) -->
<section> <!-- a thematic part, with its heading -->
<h2>Le riad</h2> …
</section>
<article> <!-- self-contained content: review, blog post -->
<h2>« Un séjour inoubliable »</h2>
<p>Accueil chaleureux, chambre impeccable. — Sophie, Lyon</p>
</article>
<aside> <!-- side content: box, related links -->
<p>Offre : -15 % pour 5 nuits et plus.</p>
</aside>
</main>
<footer> <!-- footer: address, legal notices -->
<p>Derb Sidi Bouloukat, Marrakech</p>
</footer>
</body>
| Tag | When to use it |
|---|---|
header |
introduction of a page or a section |
nav |
an important block of navigation links (not every link) |
main |
the content specific to the page, only once |
section |
a thematic part that has a heading |
article |
content that would make sense on its own (a review, a product sheet) |
aside |
secondary content |
footer |
footer of a page or a section |
div |
a container with no meaning, only for layout |
Why it matters: a screen reader announces "navigation" and "main content" and lets the user go there directly; Google understands your page better; and your CSS is easier to read.
6. Links
<!-- Absolute link: to another site -->
<a href="https://www.visitmorocco.com/fr">Office national marocain du tourisme</a>
<!-- Relative links: to a page on the same site -->
<a href="chambres.html">Nos chambres</a> <!-- same folder -->
<a href="chambres/suite-atlas.html">Suite Atlas</a> <!-- subfolder -->
<a href="../index.html">Accueil</a> <!-- parent folder -->
<a href="/tarifs.html">Tarifs</a> <!-- from the site root -->
<!-- Anchor: to a location in the page -->
<a href="#contact">Nous contacter</a>
<section id="contact"> … </section>
<!-- Email -->
<a href="mailto:contact@riad-yasmine.ma">contact@riad-yasmine.ma</a>
<!-- Open in a new tab: keep this for external links -->
<a href="https://maps.example.com/riad" target="_blank" rel="noopener">Plan d'accès</a>
Quality rules:
- the link text must say where it leads: "See our rooms" rather than "click here" (screen readers list links out of context);
- prefer relative links inside your site: it will keep working locally, in testing and in production;
- an
idmust be unique in the page.
7. Images
<img src="images/patio.jpg"
alt="Le patio du riad et sa fontaine en zellige vert"
width="800" height="533">
src: the path of the image (same rules as links);alt: the alternative text, read by screen readers and displayed if the image does not load. Describe what the image brings. For a purely decorative image:alt=""(empty, but present);widthandheight: the real dimensions in pixels. The browser reserves the space before loading, so the page does not "jump" (lesson 4.2).
Image with a caption:
<figure>
<img src="images/terrasse.webp" alt="Terrasse au coucher du soleil, vue sur la Koutoubia" width="1200" height="800">
<figcaption>La terrasse, où le thé est servi à 17 h.</figcaption>
</figure>
Formats to know: JPEG (photos), PNG (logos, transparency), WebP / AVIF (lighter photos, preferred), SVG (vector drawings, icons: sharp at any size).
8. Special characters and validation
Some characters have a meaning in HTML; to display them, you use entities:
| Character | Entity |
|---|---|
< |
< |
> |
> |
& |
& |
" |
" |
non-breaking space (1 200 DH on a single line) |
|
Thanks to utf-8, accents and Arabic are written directly, without entities.
To check a page, the W3C validator (validator.w3.org) reports badly closed tags, unknown attributes or duplicate id values. The browser, on the other hand, silently "repairs" errors… in its own way, which differs from one browser to another.
9. Organizing a site's files
riad/
├── index.html ← the home page (name expected by web servers)
├── chambres.html
├── style.css
├── app.js
└── images/
├── patio.jpg
└── terrasse.webp
Tips: file names in lowercase, without spaces or accents (suite-atlas.html, not Suite Atlas.html). A Linux server distinguishes Patio.jpg from patio.jpg, but Windows does not: this is the first cause of broken images after going live.
Common pitfalls
- Forgetting
<meta charset="utf-8">: accents display badly as soon as the site goes live. - Choosing a heading for its size (
h4because it is "smaller"): the page outline becomes inconsistent. Keep the logical order and set the size in CSS. - Images without
altor withalt="image": useless for a blind user and bad for search ranking. - Building everything with
<div>: the page works, but it says nothing to screen readers and search engines.
Lab
You will build, step by step, two pages of Riad Yasmine in /root/riad:
- the skeleton of
index.html; - its semantic structure, with only one
h1; - the menu (relative links and anchor) and the contact section;
- an image with alternative text and dimensions;
- the
chambres.htmlpage with a list and a link back.
To write a file, the simplest way is cat > /root/riad/index.html <<'EOF', then the content, then a line EOF. Read your file again with cat.
Quiz
- Which three lines must appear in the
<head>of every page? - What is the difference between
<section>and<div>? - Write a link to the page
tarifs.htmllocated in the parent folder. - What do you put in the
altattribute of a purely decorative image? - Why should you specify
widthandheighton an image?
Answers
<meta charset="utf-8">,<meta name="viewport" content="width=device-width, initial-scale=1">and<title>…</title>.<section>has a meaning (a thematic part, with a heading);<div>has none and only groups elements for layout.<a href="../tarifs.html">Nos tarifs</a>.- An empty text,
alt="": the attribute is present, and the screen reader ignores the image. - So that the browser reserves the space for the image before it loads: the page does not shift while it is displayed.
Reference sources: MDN Web Docs in French (CC BY-SA 2.5 license). Original MasterLinux text.