HTML DOM Tree Viewer
Draws the structure of pasted markup and then measures it: nesting depth, the share of elements that are plain divs, heading order and missing alt attributes.
└─ div.wrap
├─ header#top
│ ├─ h1 "The title"
│ └─ nav
│ └─ ul
│ ├─ li
│ │ └─ a "Home"
│ └─ li
│ └─ a "About"
└─ main
├─ section.hero
│ ├─ h3 "A heading that skipped a level"
│ ├─ p "Some copy."
│ ├─ img
│ └─ img
└─ div
└─ div
└─ div
└─ span "Nested for no reason"
Elements 19
Deepest nesting 6 levels
reading shallow enough that the indentation still tells you where you are
Divs and spans 5, 26.3% of all elements
reading a reasonable share: most elements here say what they are
Most common tags
div 4
li 2
a 2
img 2
header 1
h1 1
Headings 2
first one h1, "The title"
h1 count 1
levels skipped 1, such as jumping to h3
Worth looking at
images with no alt attribute 1, which is different from alt="" and is never correct
elements with over six classes 0
inline style attributes 1
19 elements, 6 levels deep, 26.3% of them divs or spans. Those three
numbers describe the shape of a page better than reading it does, and
the third is the one that predicts how it will behave for anybody
navigating by landmarks.
The nesting is shallow enough to follow. Past about a dozen levels the
indentation stops helping and starts hiding the structure it is meant to
show.
1 image here has no alt attribute at all. That is not the same as
alt="": an empty alt says the image is decorative, and a missing one
says nobody decided.
Heading levels are what a screen reader uses to skim a page, which is
why a skipped level matters more than it looks: it implies a section
that is not there.
1 element carries an inline style attribute. Each one outranks your
stylesheet, cannot be overridden without !important, and is invisible to
anybody looking in the CSS for why something looks wrong.
This is a parser rather than a regular expression, so an unclosed
element is closed at its parent and a "<" inside a script is not a tag.
What you see is what a browser would build, near enough to be useful.
A tree is a diagnosis, not a plan. The useful next step is usually
replacing a handful of the divs with the elements that say what they
are: header, nav, main, section, article, footer.
Output is valid and updates as you type.
Fix the highlighted fields to update the output.
Pasted markup is unreadable for one of two reasons. Either it is minified, which a formatter fixes, or it is nested so deeply that the indentation has stopped meaning anything, which nothing fixes by reformatting.
This is for the second case. It draws the structure, and then measures it: how deep the tree goes, what share of the elements are plain divs and spans, whether the headings are in order, and whether any image is missing an alt attribute rather than having an empty one.
Three numbers describe the shape of a page better than reading it does. Element count, depth, and the div share. The third is the one that predicts how the page behaves for somebody navigating by landmarks.
How to use
- Paste the markup. A fragment is fine; a whole page is fine.
- Read the tree, then the measurements underneath it.
- Set a depth limit if the interesting structure is in the first few levels.
Example
└─ div.wrap
├─ header#top
│ ├─ h1 "The title"
│ └─ nav
│ └─ ul
│ ├─ li
│ │ └─ a "Home"
│ └─ li
│ └─ a "About"
└─ main
├─ section.hero
│ ├─ h3 "A heading that skipped a level"
│ ├─ p "Some copy."
│ ├─ img
│ └─ img
└─ div
└─ div
└─ div
└─ span "Nested for no reason"
Elements 26
Deepest nesting 15 levels
reading past 12 levels the indentation has stopped conveying structure
Divs and spans 14, 53.8% of all elements
reading more than half the elements carry no meaning of their own
Headings 2
first one h1, "The title"
h1 count 1
levels skipped 1, such as jumping to h3
Worth looking at
images with no alt attribute 1, which is different from alt="" and is never correct
elements with over six classes 0
inline style attributes 1
The h1 followed by an h3 is the most common heading mistake there is, and it is invisible when reading the page: visually the h3 looks like the next thing down.
Pitfalls
A missing alt is not an empty alt. alt="" says the image is decorative, which is a decision. No alt at
all says nobody decided, and a screen reader falls back to reading the filename.
One h1 per document. Everything else hangs below it. Several h1s flattens the outline that headings exist to provide.
A skipped level implies a section that is not there. Going from h1 to h3 tells anybody skimming by heading that they have missed something.
Depth costs more than readability. Deep trees make layout slower, selectors longer and CSS harder to reason about. Past about a dozen levels, something in the middle is almost always unnecessary.
Div share is a proxy, not a verdict. A page can be perfectly accessible with plenty of divs. Above half, though, there are usually landmarks missing: header, nav, main, footer.
Inline styles outrank your stylesheet. Each one needs !important to override and is invisible to anybody
reading the CSS to find out why something looks wrong.
The tree is a diagnosis, not a plan. The useful next step is replacing a handful of divs with elements that say what they are.
Compatibility
Runs in the browser: nothing is uploaded and nothing is stored.
The parsing is the project’s own HTML parser rather than a regular expression, so void elements never take children, script and style contents are raw text, and an unclosed element is closed by its parent instead of swallowing the rest of the document. What the tree shows is close to what a browser would build.
The alt check uses a helper that asks whether the attribute is present at all, because the usual accessor returns an empty string for both a missing attribute and an empty one, and those mean different things. The test suite pins that distinction.
The heading checks read every heading in document order, which is the order a screen reader uses, rather than by position on the page. A level counts as skipped when it is more than one below the previous heading.
Depth is measured in element levels, not in characters of indentation, so reformatting the input does not change any of the numbers.
Frequently asked questions
Why does the element count differ from my editor’s?
What counts as a hollow element?
div and span. Both are grouping elements with no meaning of their own, which is exactly their purpose and
also why a page made mostly of them has no structure to navigate.Is deep nesting always bad?
How do I fix a div-heavy page?
header, nav, main and footer already, in
everything but name. Renaming those four is often most of the improvement.Does it handle a whole page with scripts in it?
< inside JavaScript is not read as a tag.