Build1 distinct publisher3 min readUpdated
The HTML parser repairs a div inside a p. DOM APIs do not. That asymmetry lets one React component produce two different trees, depending on where it rendered.
The Engineer · Build desk

Compiled by The EngineerSomething wrong?How this is made
A walkthrough published on dev.to under the title "Does React Break HTML Rules? Let's Find Out" traces a familiar-looking React bug back to something that is not React's doing: invalid nesting is repaired when markup travels through the browser's HTML parser, and is not repaired when the same tree is assembled through DOM APIs [12][6]. The consequence for anyone shipping server-side rendering is that identical component code can legitimately yield two different DOM trees, and the mismatch is structural rather than cosmetic [13].
Start with the canonical offender. A `p` element may contain only phrasing content, so a `div` inside it is invalid [1]. Feed the browser `<p>Hello<div>World</div></p>` as markup and the resulting DOM is closer to `<p>Hello</p><div>World</div><p></p>` [2]. The parser's rules close the open `p` when the `div` start tag arrives, and the original closing `</p>` then accounts for the stray empty paragraph at the end [3].
Write the same thing as JSX and React warns about the invalid nesting, but during client rendering the DOM can still end up with the `div` sitting inside the `p` [4]. The tempting conclusion is that React treats HTML differently from the browser. The author's test removes React entirely: `document.createElement("p")`, `document.createElement("div")`, `appendChild`, and the div is inside the p again [5]. React was not the variable. The variable is the route to the DOM: an HTML string is parsed by a component with a large rule set, including rules for recovering from invalid markup, while DOM API calls construct and connect nodes directly with no parse step in between [6]. JSX resembles HTML, but in normal client rendering React is not handing an HTML document to the parser for interpretation [7].
The second example is sharper because it is specified behaviour. Given an `image` start tag in markup, the parser treats it as a parse error, renames the tag to `img`, and reprocesses it, so `<image src="cat.png">` becomes `<img src="cat.png">` [8]. Call `document.createElement("image")` and you get exactly the element you asked for; because `image` is not a recognised HTML element name, browsers represent it as an `HTMLUnknownElement` [9].
Server-side rendering puts the parser back in the pipeline. React produces HTML on the server, that HTML reaches the browser, the parser turns it into a DOM, and only then does hydration run [10]. If the server-rendered HTML contains invalid nesting and the parser repairs it, React can arrive to hydrate a tree that is not the tree it expected [11].
The practical reading is a testing gap. A component that renders block content inside a paragraph behaves consistently in a client-only render, because nothing repairs it there, and diverges only once the same markup passes through the parser on the SSR path [13]. Nesting warnings in development are therefore worth treating as correctness failures rather than lint noise, particularly in shared layout components and third-party wrappers that decide what tag encloses your children. The source is a single author's write-up, and it stops short of cataloguing React's own guidance on the subject, so the invariant is the useful takeaway: parser output and programmatic construction are not the same tree.
Follow any of these and your For You feed starts watching them — no settings page required.
Ranked by verification strength, evidence, and original report placement.
When the HTML parser encounters an image start tag it treats it as a parse error, changes the tag name to img, and processes it again, so <image src="cat.png"> becomes <img src="cat.png">; this behaviour is in the HTML specification.
If the server sends invalid nesting, the browser parses that HTML before hydration starts, and if the parser repairs the structure React can find a DOM tree that does not match what it expected to hydrate, producing a hydration mismatch.
A p element can only contain phrasing content, so a div cannot be nested inside it.
Given the markup <p>Hello<div>World</div></p>, inspecting the DOM yields something closer to <p>Hello</p><div>World</div><p></p>, with the div no longer inside the paragraph.
When the HTML parser encounters the div, its parsing rules close the open p first; when it later reaches the original closing </p> it has to deal with that too, which is how an empty paragraph can appear.
With React removed, document.createElement("p"), document.createElement("div"), p.appendChild(div) and document.body.appendChild(p) constructs a div inside a p in the DOM using plain JavaScript.
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
One hands-on post; mechanics inspectable, framework half unshown
The core parser-versus-DOM-API asymmetry is demonstrated with short reproducible snippets and reported DevTools output, and the image-to-img rename is attributed to the HTML specification, which makes those claims easy to check independently. But everything comes from a single dev.to author with no corroborating publisher, no spec section citation, and no React version or output for the React client-rendering claim on which the article's headline conclusion depends.
No adoption signal in supplied material
The cluster contains no release, deployment, benchmark, usage disclosure, pricing, or licensing event, and no data on how often invalid-nesting hydration mismatches actually occur in deployed applications. Nothing in the source supports an adoption measurement, so none is inferred.
Clickbait headline, largely self-correcting body
The framing 'Does React Break HTML Rules?' overstates the finding, and the piece leans on suspense ('let's annoy React'). It then explicitly retracts the premise, concluding the author was comparing HTML parsing with programmatic DOM construction and that React was not the important part. The residual overstatement is small and concentrated in the unshown React client-rendering step and the generalised two-trees conclusion drawn from it.
Personal developer-audience post, no product stake visible
The only visible incentive is reputation and audience building on a developer publishing platform under an individual handle; the piece promotes no product, vendor, service, or paid offering, and criticises no competitor. The mild distortion pressure is engagement-driven headline framing rather than commercial interest. Nothing in the supplied material discloses employer or sponsorship, so this reflects only what is observable.
Mechanics credible and checkable; framework specifics unverified
Confidence is moderate: the parser-recovery and DOM-API behaviours described are internally consistent, spec-attributed, and reproducible from the snippets given, which raises trust in the general model. It is held down by having exactly one publisher, no corroborating source, an unmeasurable adoption dimension, and a load-bearing React claim shown only as recollection.
build
The Escape-key listener you cannot fix with a dependency array1 distinct publisher
build
Codex learns to click: the coding agent stops typing patches and starts operating the machine1 distinct publisher
build
Five frameworks, one store, and a benchmark that measures when the button works1 distinct publisher
build
The 35% Lift Was The Tide: What A Bundled Commit Hid About Which Fix Worked1 distinct publisher
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · August 15, 2026