Dom Is Not The Html File

The DOM and your HTML file are not the same thing. DevTools shows you one. View Source shows you the other. Knowing the difference changes how you debug.

May 1, 20264 min read4 / 12

Before I write a single line of JavaScript that manipulates the page, I want to nail one distinction that tripped me up for longer than I'd like to admit: the DOM is not your HTML file.

These are two separate things. Knowing which one you are looking at changes how you read the browser, how you debug, and how you reason about what your code is actually doing.

The Essentials

  1. HTML file: A string on disk. A sequence of characters that the browser reads. It never changes at runtime.
  2. DOM: A tree of objects in memory that the browser builds by parsing the HTML string. This is what JavaScript interacts with.
  3. View Source: Shows the original HTML string. What you sent from the server.
  4. DevTools Inspector: Shows the current DOM tree. What the browser built from that string, plus any changes JavaScript has made since then.
  5. Implicit structure: Every page has <html>, <head>, and <body> in its DOM, even if you never wrote them. They are required by the DOM spec, not by the HTML spec.

View Source vs Inspect: Two Different Things

Right-click any page and you have two options: "View Page Source" and "Inspect."

These look similar. Both show you HTML-like markup. But they are completely different things.

View Source shows you the HTML string that was delivered by the server. That is frozen. It represents what was sent over the wire and nothing else. JavaScript running on the page cannot change what View Source shows you, because JavaScript cannot change the file that was served.

The DevTools Inspector shows you the DOM. That is live. Every time JavaScript adds an element, updates a class, or injects content, the Inspector reflects it immediately. If a React app renders 300 components after page load, those 300 elements appear in the Inspector but not in View Source.

I used to mix these up constantly when debugging. I would look at View Source to check if an element was there, not find it, and assume my JavaScript was broken. But the element was added after the initial HTML loaded. View Source would never show it. The Inspector would.

The browser builds the DOM by parsing the HTML source, but the relationship between the two is not 1:1. The DOM can diverge significantly from the original HTML once JavaScript has run.

The HTML Spec Permits What You Would Not Expect

Here is a useful demonstration. Open a file that contains only this:

HTML
<!DOCTYPE html> <title>Test</title> <h1>Hello</h1>

No <html> tag. No <head> or <body>. No closing tags other than what is shown.

Run it through the W3C HTML validator. It passes. This is valid HTML.

Now inspect it in DevTools. What you see is not what you wrote:

Plain text
html head title "Test" body h1 "Hello"

The browser added <html>, <head>, and <body> for you. You did not write them. They are not in the HTML string. But they are in the DOM.

This is not the browser making a mistake. It is the browser following the spec. The HTML specification says these elements are optional in the source file. The DOM specification says they are required. So the browser builds a compliant DOM from whatever HTML you give it, filling in what is absent.

Now push it further. Add a style targeting the body even though you never declared a body:

HTML
<!DOCTYPE html> <title>Test</title> <style> body { background-color: red; } </style> <h1>Hello</h1>

The background turns red. Because the DOM has a body. You just did not write it.

How the Browser Decides What Goes Where

When the browser parses your HTML string without explicit <head> or <body> tags, it uses a simple rule: anything that is not visible goes into the head. The first visible thing starts the body.

Meta tags, title, link elements, script tags: these are not visible. They go to the head.

A paragraph, a heading, a div, even raw text not wrapped in any tag: visible. Body starts here.

This is why you can write a perfectly functional page with no structural wrapper tags at all. The browser will place everything correctly because it knows which things are visible and which are not.

What This Means in Practice

Two things follow from this that are worth keeping in your mental model:

First, when you debug a vanilla JavaScript app and something looks wrong in the Inspector but fine in View Source, the explanation is usually that JavaScript changed the DOM after load. The source is frozen. The DOM is live. Look at the Inspector.

Second, the DOM you are manipulating in JavaScript has structure the HTML file may not show. Every document has a document.documentElement (the <html> element), a document.head, and a document.body, even if none of them appear in the original HTML. You can always access these safely.

Understanding this separation, HTML as source and DOM as in-memory structure, is the foundation for everything that comes next when working with the browser's APIs directly.

Further Reading and Watching

  • MDN: DOM Introduction - Covers the relationship between the HTML source and the DOM tree.
  • W3C HTML Validator - Try validating a minimal HTML file without explicit structural elements to see what it accepts.

Video: