Elements, attributes and the tree
Your file is a suggestion. What the browser builds from it is a tree, and the two are not always the same document.
An element is a node. Its children are nodes. Text is a node too, which surprises people the first time they count them and find whitespace in the list. Attributes hang off elements as name-value pairs, and the tree the browser builds from all of this is the thing every other part of the stack talks to: CSS selects against it, JavaScript walks it, screen readers read it, search engines index it.
Your HTML file is not that tree. It is a description the parser reads, and the parser is extremely forgiving, by specification, not by accident. HTML has no parse errors in the sense that JSON or JavaScript does. Feed it something malformed and it will not stop; it will repair the damage using a documented recovery algorithm and hand you a tree. That tree may not be the one you had in mind.
This matters more than it sounds, because it is the mechanism behind a whole family of bugs that look supernatural. A stylesheet rule that "does not apply" when the element is clearly right there. A component that renders in the wrong place. A <div> that has somehow become a sibling of the thing you nested it inside. In every case, the source says one thing and the tree says another, and only the tree is real.
The instrument below runs a small parser with the common recoveries in it. Try the presets before you type your own: an unclosed paragraph, a block element inside a <p>, a <li> with no list around it, mismatched closing tags. Read the "what the browser did that you did not write" panel each time. Those corrections are not the parser being clever, they are the parser following rules written down two decades ago, which every browser implements identically, and which you can therefore rely on.
What the parser builds
type in the box- Implied </p> before <ul>A <p> can only hold text and inline elements. Meeting <ul> ends it, so the <ul> you wrote inside the paragraph is now its next sibling, not its child.
- Implied </li> before <li>Two <li> elements cannot nest, so the previous one is closed here. Leaving them unclosed works, until you style or query the descendants and find they belong to a different item than you thought.
- Implied </li></ul> arrived while <li> was still open. The parser cannot close them out of order, so it closes <li> here: the crossed tags you wrote become properly nested ones you did not.
3 repairs. None of them was reported to you. The page still loads, the CSS still applies, to a structure that is no longer the one in your editor.
This parser handles the recoveries you meet first: implied end tags, crossed tags, void elements, duplicate attributes, an item with no list. The HTML5 parsing algorithm is far longer: it has separate rules for tables, forms, foreign content and a list of formatting elements it re-opens for you. Nothing here is a substitute for the spec; it is a demonstration that the repair is happening at all.
One more distinction to bank now, because it causes confusion for years otherwise: an attribute and a property are not the same thing. <input value="hi"> sets the attribute, which is the initial value. Typing in the field changes the property, which is the current value. Read el.getAttribute('value') after typing and you get "hi"; read el.value and you get what the user typed. The HTML is the seed, the DOM is the living thing, and they diverge the moment anyone interacts.
Go and look at your own page in the Elements panel with this in mind. It is not showing you your file. It is showing you the tree, live, including anything JavaScript has changed since load. Right-click an element and choose "Edit as HTML" to see the serialised form of what is actually there, which, on a generated page, is frequently not what is in your source at all.
You should now be able to
- Describe how a parser turns text into a node tree
- Predict what a browser does with markup you got wrong
- Tell the difference between an attribute and a property
- Read the Elements panel as the tree rather than as your source
Loading…