Every HTML page shares the same outer skeleton. It is only a few lines long, but each line changes how browsers, screen readers and search engines treat the page.
The minimal valid document
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Opening times | Riverside Bakery</title>
</head>
<body>
<h1>Opening times</h1>
<p>Monday to Saturday, 7am to 4pm.</p>
</body>
</html>
That is everything a valid page needs. Let us take it line by line.
The doctype
<!DOCTYPE html>
The doctype is not an element. It is an instruction that tells the browser to use standards mode, the mode in which it follows current specifications.
Without it, browsers switch to quirks mode, which imitates bugs from browsers of the late 1990s so that very old pages still display as they did. In quirks mode, the box model, table sizing and some CSS behave differently, and you will chase layout bugs that do not exist in standards mode.
- It must be the very first thing in the file, before any element.
- It is not case-sensitive:
<!doctype html>works just as well. - Older doctypes, such as long XHTML or HTML 4.01 declarations, are not needed. Use the short form.
To check which mode a page is in, open the DevTools Console and type document.compatMode. "CSS1Compat" means standards mode; "BackCompat" means quirks mode.
The html element
<html lang="en">
...
</html>
The html element is the root. Every other element sits inside it. It has exactly two children: head and body.
The lang attribute
lang declares the main language of the page. It uses a language tag such as:
| Tag | Language |
|---|---|
en | English |
en-GB | English as used in the United Kingdom |
en-AU | English as used in Australia |
fr | French |
es | Spanish |
zh-Hans | Chinese in simplified script |
It looks like a small detail, but it does real work:
- Screen readers choose a voice and pronunciation rules from it. Without it, English text might be read with a French accent and pronunciation, or the reverse.
- Browsers use it to decide whether to offer translation, to choose fonts for some scripts, and to apply language-specific rules such as hyphenation with CSS
hyphens: auto. - Accessibility standards require it. WCAG success criterion 3.1.1 (Language of Page) is met by setting
langon thehtmlelement.
When part of a page is in another language, mark that part with its own lang:
<p>The French call it <span lang="fr">pain au chocolat</span>.</p>
Do not copy a template with lang="en" into a site written in another language and forget to change it. A wrong lang value is worse than an obvious bug, because nobody notices it until a screen reader user does.
The head element
<head>
<meta charset="utf-8">
<title>Opening times | Riverside Bakery</title>
</head>
The head holds information about the page rather than content shown on it. Nothing inside head appears in the page area itself. Typical contents:
meta charsetdeclares the character encoding.titlesets the text in the browser tab, in bookmarks and usually in search results.meta name="viewport"controls how the page fits mobile screens.linkelements load stylesheets and icons.scriptelements load JavaScript.
The next lesson covers each of these in detail. For now, remember the two that every page needs: meta charset and title.
The body element
<body>
<h1>Opening times</h1>
<p>Monday to Saturday, 7am to 4pm.</p>
</body>
The body contains everything visitors see and interact with: headings, text, images, links, forms and so on. There is exactly one body per document.
What browsers do if you leave things out
The HTML parser is forgiving. If you leave out html, head or body, the browser creates them in the DOM anyway. This is technically valid HTML:
<!DOCTYPE html>
<meta charset="utf-8">
<title>Tiny page</title>
<p>Hello.</p>
You can see the missing elements appear in the DevTools Elements panel. Do not rely on this. Writing the full skeleton makes your intent clear, gives you a place for lang, and avoids confusion when content ends up in the wrong place. For example, if a stray element appears before your meta tags, the browser may close the head early and push the rest into the body.
A good starting template
This template adds the viewport line from the next lesson. Use it as the starting point for every exercise in this course:
<!DOCTYPE html>
<html lang="en-GB">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Page title | Site name</title>
</head>
<body>
<h1>Page title</h1>
<p>Content goes here.</p>
</body>
</html>
Common mistakes
| Mistake | What happens | Fix |
|---|---|---|
| No doctype | Quirks mode and odd layout bugs | Add <!DOCTYPE html> as the first line |
Content inside head | The browser moves it into body and may ignore later metadata | Keep visible content in body |
Missing lang | Screen readers guess the language, often wrongly | Add lang to the html element |
Two body elements | The second one is merged into the first | Use one body per page |
Summary
- Start every page with
<!DOCTYPE html>to get standards mode. htmlis the root element and has two children,headandbody.- Set
langonhtmlso screen readers, browsers and translation tools know the page language. headholds metadata;bodyholds visible content.- Browsers fill in missing elements, but writing the full skeleton avoids subtle bugs.