UrsaKit cover explaining the structure of an HTML document

HTML is a forgiving language, and that is exactly why markup bugs survive: the browser silently repairs what you wrote, so the page looks fine while the document is not what you think it is. This guide covers the structure a document actually needs, the parts that are optional but matter, and the mistakes that produce layout differences weeks later.

You can test every example in the UrsaKit HTML online tool, which renders your markup in a sandboxed preview as you type.

01The browser is forgiving, which is the problem

Feed a browser an unclosed <div>, a table with mismatched cells, or a paragraph nested inside another paragraph, and it will not error — it will guess. The HTML parsing algorithm is specified in detail precisely because that guessing must be consistent across browsers.

The practical downside is that the DOM you get is not always the DOM you wrote. A <p> inside a <p> closes the first paragraph, a <div> inside <table> gets moved outside it, and invalid nesting in <ul> becomes text nodes.

The only reliable way to see what you actually produced is to inspect the rendered DOM, not the source file. Every browser's developer tools show the parsed tree.

02The five lines every document needs

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Page title</title>
  </head>
  <body>
    <h1>One heading, describing the page</h1>
  </body>
</html>

Each line has a job that is invisible until it is missing:

  • <!doctype html> switches the browser out of quirks mode. Without it, box sizing, percentage heights and line height follow legacy rules.
  • lang tells screen readers which pronunciation to use and lets the browser hyphenate correctly. Use a real tag such as zh-Hant or es.
  • charset must come first in the head. Wrong or late charset turns every non-ASCII character into mojibake.
  • viewport is what makes a page mobile-friendly; without it phones render at a simulated 980-pixel width.
  • title is the label in tabs, bookmarks and search results.

One h1 per page.

The h1 is the page's subject. If every section starts with an h1, neither search engines nor screen reader users can tell what the page is about. Use h2 for sections and h3 for subsections inside them.

03head versus body

The head contains information about the document; the body contains what the user sees. Mixing them is one of the most common sources of confusion.

Belongs in headBelongs in body
title, meta, linkh1–h6, p, ul
style for the whole pageElements the user reads or clicks
script with deferscript at the end of the body
Favicon and preload hintstemplate and noscript fallbacks

Content placed in the head is not rendered; markup placed in the body that belongs in the head is moved or ignored. If a stylesheet link seems to do nothing, check whether it ended up in the body.

04Void elements and escaping

Some elements have no content and no closing tag. They are called void elements, and writing </img> is a parse error even though browsers tolerate it.

<img src="/logo.png" alt="UrsaKit logo" width="1161" height="389" />
<input type="email" name="email" required />
<br />
<hr />
<meta charset="utf-8" />

Two rules cover most escaping bugs:

  • Ampersands start an entity. Write &amp; for a literal &, otherwise & may begin a character reference and change the text.
  • Quotes inside attributes. Wrap attribute values in double quotes and escape inner double quotes as &quot;, or switch the attribute to single quotes.

Always set width and height on images. The browser reserves the space before the file loads, which prevents the layout shift that ruins reading position and Core Web Vitals.

05What semantic elements actually change

section, article, nav and div all render as blocks with no default style. Choosing between them does not affect pixels, so teams often give up and use div everywhere. That trade has real costs:

  • Screen readers can jump between landmarks only when the markup defines them.
  • Crawlers use headings and landmarks to work out which part of a page is the main content.
  • Your own CSS and tests get selectors such as nav ul instead of .wrapper-3 ul.
ElementUse it for
header / footerPage or section intro and closing content
navA group of navigation links
mainThe single main content area, once per page
articleContent that would make sense on its own
sectionA themed group with its own heading
divA container that exists only for styling

06Seven markup mistakes worth fixing

MistakeWhat actually happensFix
No doctypeQuirks mode changes box sizing and height rulesAdd <!doctype html>
lang missing or wrongWrong pronunciation, wrong hyphenationSet the real language tag
Charset not first in headNon-ASCII text becomes mojibakePut meta charset first
<div> inside <table>The div is moved outside the tableUse thead, tbody, tr, td
Block element inside pThe paragraph closes earlyClose the paragraph, then start the block
script without defer in headParsing waits for the script to download and runAdd defer or move it to the end
Duplicate id attributesgetElementById and label associations hit the first oneKeep ids unique

07Test markup without a build step

  1. Paste a full document or a fragment — The HTML tool accepts both. A fragment is wrapped in a minimal document, so you can check a component in isolation.
  2. Watch the preview as you type — The preview renders in a sandboxed frame, so scripts run without touching the tool's own page.
  3. Compare against the DOM, not your source — When something looks wrong, inspect the element in the preview. Browsers repair markup, and only the parsed tree tells you what you built.
  4. Move to styling — Once the structure is right, take the same markup into the CSS playground to work on layout, or run behaviour against it in the JavaScript runner.

Keeping the structure correct from the start is cheaper than finding out later that a layout bug was an HTML bug.

Frequently asked questions

Do I still need to write the doctype?

Yes. Without it, browsers use quirks mode, where box sizing and line height follow legacy rules and layouts break in ways that are hard to trace.

Is the html, head and body structure optional?

The browser inserts them if you omit them, but write them explicitly. Implicit elements are invisible in your source, which makes debugging slower than typing four extra tags.

What does the lang attribute change?

It tells screen readers which voice to use, tells the browser how to hyphenate and quote, and helps search engines understand the page language.

Where should a script tag go?

In the head with defer, or at the end of the body. A plain script tag in the head blocks parsing until the file has downloaded and run.

Are self-closing tags valid in HTML?

The trailing slash is ignored for void elements such as img or br, so img src="x" / is valid but meaningless. On non-void elements it is a parse error.

Does semantic markup change how the page looks?

No. section, article and div render identically. Semantics change what assistive technology and crawlers understand, and give CSS and JavaScript meaningful hooks.

Back to articles

Related articles

Related tools