Boneyard Tools

How HTML indentation and void elements work

Why a beautifier indents by nesting depth, how void and raw elements are treated, and what whitespace collapsing does to your markup.

Indentation follows nesting depth

A formatter does not guess at pretty spacing, it tracks how deeply nested each tag is. Every open tag adds one to a depth counter and every matching close tag subtracts one. The number of indent units on a line equals the current depth, so a list item inside a list sits one level in, and a link inside that item would sit two levels in. This is why turning a single minified line into a readable tree is really just counting opens and closes.

Void elements never nest

The HTML specification defines a set of void elements, including area, base, br, col, embed, hr, img, input, link, meta, source, track and wbr. They have no content and no closing tag, so it would be wrong to indent anything after them as though it were a child. The formatter recognises these names and leaves the depth unchanged, which keeps siblings that follow an image or a line break aligned with it rather than stepping to the right forever.

Raw elements are left alone

Some elements hold content that must survive exactly as authored. Inside pre and textarea, spaces and line breaks are meaningful and visible, while script and style hold code and CSS that are not HTML at all. Reindenting them could change how a page looks or even break a script. The tool captures each of these blocks from its opening tag to its matching closing tag and passes the whole thing through verbatim, so their insides are never touched.

Whitespace collapsing and inline text

Ordinary text between tags often arrives with ragged spacing from source formatting or copy and paste. Because browsers already collapse runs of whitespace to a single space when they render, the formatter does the same, trimming the ends too. When a tag contains only one short run of text, that text and the closing tag are kept on the opening tag's line, so a list item reads as one tidy line instead of being spread across three. The result is markup that matches how the page actually displays.

Frequently asked questions

Does a self-closing tag like a custom component indent its siblings?

No. A tag that ends with a slash before the closing angle bracket is treated like a void element, so it emits at the current depth and does not push what follows any deeper.

Why is my formatted comment kept on its own line?

Comments and doctype declarations are emitted at the current indent level without changing depth, so a comment lines up with the tags around it rather than nesting them.