Format, minify, encode entities, and validate HTML documents.
How the parser closes tags on its own, why escaping angle brackets alone is not enough, and which whitespace is significant.
The HTML parsing algorithm follows each element content model rather than your indentation. A `<p>` accepts only phrasing content, so `<p><div>x</div></p>` yields an empty paragraph, a div and a second empty paragraph: the opening `<div>` implies the end of the paragraph. The same happens to an `<li>` without a `<ul>`, `<ol>` or `<menu>` ancestor, and to stray text inside `<table>`, which the parser relocates before the table through foster parenting. `<main>` maps to the `main` ARIA role and should appear once per document, while `<h1>` through `<h6>` feed the accessibility tree by their literal number, never recalculated from nesting depth.
HTML defines five named references: `<`, `>`, `&`, `"` and `'`. The last one did not exist in HTML 4, so legacy templates are safer with `'`. Escaping those five characters is enough inside a text node and insufficient everywhere else: in an unquoted attribute a single space lets an attacker append `onmouseover=`; inside `<script>` the parser stops at the literal `</script>` sequence even within a string; and in `href` no entity prevents a `javascript:` payload. Correct escaping therefore depends on the insertion context, because text, quoted attributes, URLs, CSS and JavaScript each need different rules.
The spec allows omitting several end tags (`</li>`, `</p>`, `</td>`, the entire `<tbody>`) and the quotes around any attribute whose value contains no space, double quote, single quote, `=`, `<`, `>` or backtick, and aggressive minifiers exploit both. What they must not do is collapse every space: between two inline elements `</span> <span>` renders a visible space, and removing it glues the words together. `<pre>` and `<textarea>` keep literal whitespace, with one parser exception — a newline immediately after the start tag is discarded. This is why minified HTML typically shrinks only 10% to 20%, far less than CSS or JavaScript.
Not per the specification: every `<section>` may carry its own `<h1>`. The practical problem is that the outline algorithm meant to recompute heading levels was never implemented and has been dropped from the standard, so screen readers and crawlers read the literal tag number. Skipping from `<h2>` to `<h4>` does break heading navigation.
Because whitespace between inline elements is rendered. When a formatter turns `<span>a</span><span>b</span>` into two indented lines, a space appears between them, and in an `inline-block` row that indentation adds roughly 4px gaps. The usual fix is `display: flex` on the container instead of fighting the line breaks.
They belong to different layers. `&` is markup escaping: in `href="/search?a=1&b=2"` the browser hands the URL over with a plain `&`, and leaving it unescaped is risky because sequences such as `©=` are parsed as a character reference. `%26` is percent-encoding and is required when the `&` is part of a parameter value, as in `?company=Ruiz%20%26%20Sons`.