---
title: 'Document Type and Root Structure'
source: 'https://academia.sh/en/courses/web-fundamentals-and-html/document-type-and-root-structure'
course: 'Web Fundamentals and HTML'
language: en
updated: '2026-08-17T18:09:31+00:00'
license: 'CC BY-SA 4.0'
---

# Document Type and Root Structure

The doctype declaration's function, the root element's language declaration, the head/body split, and unwritten elements being built by the parser.

The previous topic established how the document is processed. This topic establishes how the
document is written, and starts with the outermost structure: the declarations that sit in
every HTML document's first lines and are, most of the time, copied without a second thought.

Each of these declarations answers a specific problem. Knowing which problem each one answers
also decides which are mandatory and which are conditional.

## The Doctype Declaration

A document's first line is the form `<!doctype html>`. This is not an element; it is a
declaration given to the parser, and it has a single job: choosing the parsing mode.

The reason this mode exists is backward compatibility. Some of the web's early documents were
written against rules that only became standard later; processing those documents with the
standard rules would break their appearance. The solution was to define two modes: **standards
mode** for documents that follow the standard rules, **quirks mode** for older documents. The
doctype declaration is the switch that chooses which mode a document is processed in.

The declaration's absence is not a flaw, it is a different request: the parser processes the
document in quirks mode, and that mode's rules are not the rules expected today. The
differences sit mostly in the presentation layer — how box width is computed, for example —
and are not covered in this course. The rule is clear: the declaration is written.

The declaration itself carries no other information. It has no version number, no schema
address, no language identity; it only chooses the mode.

## The Root Element and Language Declaration

A single root element comes after the doctype declaration: `html`. It is the only child after
the document node in the tree, and the whole document sits inside it.

There is one attribute that must be written on the root element: `lang`. It declares the
document's natural language, and its effect is not visual.

```html
<!doctype html>
<html lang="en">
```

The language declaration affects at least four decisions. Screen readers learn from it which
language's pronunciation rules to read the text with; a wrongly declared language makes text
unreadable. Spell checking and hyphenation-based line-breaking rules depend on the language.
Search indexers classify the document by language. Some typographic conventions — the form
quotation marks take, for example — vary by language.

If part of the document is in a different language, that part is redeclared on the element
carrying it; the attribute is inherited and the nearest declaration applies.

```html
<p>The station's Spanish name is
  <span lang="es">Estación Ladera Norte</span>.</p>
```

## Head and Body

The root element has two children, and their order never changes: `head`, then `body`.

The **head section** (`head`) carries information about the document: its title, character
encoding declaration, links to external resources, metadata. This content is not painted. Its
only visible effect is the `title` element being used in the browser tab and in bookmarks.

The **body section** (`body`) carries the document's readable content. Everything that gets
painted is here.

Even though the split looks sharp, there is one element that sits on the boundary: `script`.
A script element can be found in either section, and where it is found decides the loading
behavior seen in the previous lesson.

## Unwritten Elements Are Built

Even when the `html`, `head`, and `body` elements' tags are not written, the parser builds
them. Which element goes into the head section and which goes into the body is decided by a
defined rule: the moment an element that does not belong to the head section is seen, the head
section closes and the body begins.

```js
// root.mjs — placement of unwritten html/head/body elements
const HEAD_CONTENT = new Set(["title", "base", "link", "meta", "style", "script", "noscript"]);

function place(text) {
  const tokens = [...text.matchAll(/<\/?([a-z0-9!]+)[^>]*>/g)]
    .map((e) => ({ name: e[1], closing: e[0][1] === "/" }));
  const head = [];
  const body = [];
  let doctype = null;
  let mode = "head";
  for (const token of tokens) {
    if (token.name === "!doctype") { doctype = "html"; continue; }
    if (token.closing) continue;
    if (["html", "head", "body"].includes(token.name)) continue;
    if (mode === "head" && HEAD_CONTENT.has(token.name)) head.push(token.name);
    else { mode = "body"; body.push(token.name); }
  }
  return { doctype, head, body };
}

const documents = {
  "fully written": `<!doctype html><html lang="en"><head><meta charset="utf-8">
<title>North Slope</title></head><body><h1>North Slope</h1><p>1840 m</p></body></html>`,
  "root elements not written": `<!doctype html><meta charset="utf-8">
<title>North Slope</title><h1>North Slope</h1><p>1840 m</p>`,
  "no doctype": `<title>North Slope</title><h1>North Slope</h1>`,
};

for (const [name, doc] of Object.entries(documents)) {
  const { doctype, head, body } = place(doc);
  console.log("[" + name + "]");
  console.log("  doctype    :", doctype ?? "none -> quirks mode");
  console.log("  head       :", head.join(", "));
  console.log("  body       :", body.join(", "));
}
```

```
[fully written]
  doctype    : html
  head       : meta, title
  body       : h1, p
[root elements not written]
  doctype    : html
  head       : meta, title
  body       : h1, p
[no doctype]
  doctype    : none -> quirks mode
  head       : title
  body       : h1
```

The first two documents were written differently and produced the same structure. The third is
split by the same rule but will be processed in a different mode.

One consequence of this rule is that an element that does not belong to the head section
cannot accidentally end up written into it: even if written there, it is carried over to the
body. The reverse holds too — a `title` element written in the middle of the body does not
travel back to the head section, it stays in the body and does not do the job expected of it.
The parser's tolerance is not about silently fixing writing mistakes, it is about producing a
defined result.

Writing the tags anyway still has a justification: readability and where attributes go. The
`lang` attribute has to be written on the `html` element, a class or id on the `body` element;
for that, the tag has to be present in the source text.

## Uniqueness and Order Constraints

Four elements are unique in the root structure: a document has only one `html`, one `head`,
one `body`, and one `title`. Writing a second one does not build a new element; when the
parser sees a second `body` tag, it does not open a new body, it merges it with the existing
one's attributes. A document cannot have two bodies, because the tree has a single root and
that root has a single visible branch.

Order within the head section's content is generally free; two situations are the exception.
The character-set declaration is written as early as possible — the reason for this is the
next lesson's subject. The `base` element, which changes the base for relative addresses, is
also written early, because it affects addresses that come **after** it, and it is found only
once in the document.

The `title` element is the head section's mandatory content. If it is not written, the
document keeps being processed, but it cannot be named outside its own context: the address
shows in the tab, the bookmark is saved without a name, the text introducing the document in a
search result is generated from other sources. The requirement is not a parsing condition, it
is a condition for the document to be recognizable in the outside world.

## The Station Document's Skeleton

Here is the first version of the document that will be developed throughout the course:

```html
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>North Slope Measurement Station</title>
</head>
<body>
  <h1>North Slope Measurement Station</h1>
  <p>An automated measurement station built at an elevation of 1840 meters above sea level.</p>
</body>
</html>
```

Five lines of declaration, two lines of content. This ratio will fall as content grows in the
document; the declaration section stays fixed regardless of the document's size.

The `title` element is in the head section, the `h1` element is in the body, and their text is
the same here. The two do separate jobs: `title` names the document outside its context — in
the tab, in a bookmark, in a search result —; `h1` is the topmost heading inside the document.
Because `title` needs to be understandable outside its context, it is often written longer in
most documents and also carries the site's name.

## Summary

- The doctype declaration is not an element; it chooses the parsing mode and carries no other
  information. Without it, the document is processed in quirks mode.
- The root element is `html`, the document's single root child; the `lang` attribute affects
  pronunciation, hyphenation, indexing, and typography decisions, and is redeclared where part
  of the document is in a different language.
- The head section carries information about the document, the body carries the readable
  content; head-section content is not painted.
- The parser builds the `html`, `head`, and `body` elements even when their tags are not
  written; the split happens at the first element that does not belong to the head section.
- `title` names the document outside its context, `h1` is the topmost heading inside the
  document; their text can be the same, but their functions are separate.

## Next Step

This lesson built the document's outermost shell and used tags without going into their
syntactic detail. The next lesson takes up that detail: how a tag is written, which forms of
writing attributes accept, how the `<` and `&` characters that appear in text are written, and
which error-recovery rules the parser applies to writing that breaks the rules.
