ESC

Type to search the knowledge base.

HTML Document Structure

Skeleton of a solid HTML document — doctype, html/lang, head metadata, body landmarks, and what belongs where.

beginner3 min read
  • html
  • document-structure

A valid HTML document is more than “React root div.” The doctype, lang, head metadata, and body landmarks affect rendering mode, accessibility, SEO, and social previews.

Docs: MDN document structure, HTML living standard.

Minimal solid skeleton

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Billing settings — Frontend Beauty</title>
    <meta
      name="description"
      content="Update your plan, payment method, and invoices."
    />
    <link rel="icon" href="/icon.svg" type="image/svg+xml" />
    <link rel="stylesheet" href="/styles.css" />
  </head>
  <body>
    <a class="skip-link" href="#main">Skip to content</a>
    <header>…</header>
    <nav aria-label="Primary">…</nav>
    <main id="main">…</main>
    <footer>…</footer>
    <script type="module" src="/app.js"></script>
  </body>
</html>

Head checklist

Item Why
<!DOCTYPE html> Standards mode
lang on <html> AT pronunciation, hyphenation, search
charset early Avoid mojibake
viewport Mobile layout
Unique title Tabs, bookmarks, SEO
description Snippet candidate
Icons / manifest Branding, PWA
CSS before paint Prevent FOUC where possible
Social meta (OG/Twitter) Shares
<meta charset="utf-8" />

Place charset in the first 1024 bytes — keep it near the top of <head>.

Body structure

<body>
  <header>… site or page chrome …</header>
  <nav aria-label="Primary">…</nav>
  <main>
    <!-- one main per page -->
  </main>
  <aside>… complementary …</aside>
  <footer>…</footer>
</body>
  • One <main>
  • Label multiple <nav>s
  • Skip link as early focusable control

Scripts

<script type="module" src="/app.js"></script>

Modules defer by default. Classic scripts: use defer for ordered DOM-ready execution without blocking parser as badly as sync scripts in head.

Avoid huge inline scripts before content unless required for theme FOUC prevention (small and intentional).

SPA shells

Even with client routing, the initial HTML should include:

  • Correct lang and title
  • Meaningful shell or SSR content when possible
  • Not only <div id="root"></div> empty forever for public content pages

Interview out-loud

“I start with doctype, html lang, charset, viewport, a specific title, and description. Body uses landmarks: header, nav, one main, footer, plus a skip link. Scripts load as modules or deferred. Metadata in head covers icons and social tags when the page is shareable.”

Footguns

  1. Missing lang.
  2. Duplicate or empty titles across routes.
  3. Viewport locked against zoom (user-scalable=no) harming a11y.
  4. Multiple mains from nested layouts.
  5. Blocking scripts in head without defer/async.

Common generator output to fix

Many frameworks emit a minimal shell. Before production:

  1. Unique titles per route (SSR or prerender).
  2. Meta description for public pages.
  3. lang matching content language.
  4. Favicon links.
  5. One main landmark.
  6. Skip link.
<!-- Bad public docs shell -->
<div id="root"></div>

Ship at least a noscript message and, ideally, server-rendered article content for documentation sites.

Character set and title order

Put charset first, then title soon after. Some older guidance required title early for progress UI; modern browsers are fine as long as charset is early. Keep critical CSS and preloads near the top after basic meta. Defer analytics to the end of body. A clean head is easier to audit for SEO and performance regressions.

Further reading

Related guides