After more than 20 years of professional web development, I realized that a
element can only contain phrasing content such as text, spans, and inline formatting elements. Block-level elements like
was mostly a regular block element with default margins, but when a browser rearranged my markup, I finally looked into the rule. Was this always how HTML worked, or did browsers only recently start enforcing it?
3 Answers
This isn’t a new Chrome rule. HTML parsers have traditionally handled this by implicitly closing the open
before starting a block element. So markup like
text
gets turned into something closer to
text
. The browser still renders the page, but the DOM may not match the source you wrote.
You’re definitely not the only experienced developer who has learned this late. Browsers are extremely forgiving, so invalid nesting can appear to work for years. Tools such as editor diagnostics, validators, and browser inspectors make the issue more obvious, but the underlying content model has been around for a long time. Also, an element like has special parsing rules, so it doesn’t fit neatly into the usual block-inside-inline explanation.
A paragraph is meant to represent a paragraph of phrasing content, not act as a generic container. Use a for an inline wrapper inside the paragraph, or close the paragraph and use a
It’s easy to forget this when you’re mainly thinking about CSS. The markup may look fine visually while still producing a very different structure than intended.

That explains what I saw: the wrapper appeared outside the paragraph when I inspected the result. I had assumed the browser was only correcting it recently.