In an HTML document, what does the trailing slash in `<br />` and `<div />` mean to the HTML parser, and which elements can actually close themselves?
answer
- HTML is not XML
- some elements never take an end tag
- the slash is tolerated, then ignored
- void list is fixed by the spec
- SVG and MathML are the exception
basics
~20 sIn HTML the trailing slash is ignored. Void elements such as br, img and input never take an end tag and close themselves anyway; on an ordinary element such as div the slash does nothing, so <div /> stays open.
solid answer
~50 sHTML is not XML, so `/>` is not a self-closing mechanism. A fixed list of elements — `area`, `base`, `br`, `col`, `embed`, `hr`, `img`, `input`, `link`, `meta`, `source`, `track`, `wbr` — are **void elements**: they can never have children and never take an end tag, so `<br>` and `<br />` parse identically and the slash is purely decorative XHTML-era habit. On any non-void element the slash is a parse error that the parser ignores: `<div />` opens a div, and everything that follows becomes its children until a real `</div>` or an implied close arrives. The trap people hit most is `<script src="a.js" />` — the script element stays open and the rest of the page is swallowed as script text until a `</script>` appears. The slash only genuinely self-closes inside foreign content, that is inside `<svg>` or `<math>` subtrees.
code
html · 7 lines<div class="a" />
<p>Nested inside the div, not a sibling.</p>
</div>
<img src="a.png" alt="A">
<br />
<br>go deeper
Recall that void elements such as br, img, input, hr and meta never take an end tag, and that the trailing slash on other elements changes nothing.
Explain that the tokenizer records a self-closing flag which tree construction ignores for HTML elements, and walk through what <div /> or <script /> actually does to the following markup.
Show where this bites in production: a self-closed script or custom element that silently swallows a page section, and how you would catch it by comparing the rendered DOM against the source.
Own the convention question — whether the codebase writes XML-style slashes at all, how templating and formatting tooling normalises them, and why a house rule beats each author's XHTML muscle memory.
## HTML is not XML In XML, `<foo/>` is a complete element: the grammar says a start tag may end with `/>` and that ends the element. HTML's grammar does not work that way. The HTML tokenizer recognises the character sequence `/>` at the end of a start tag and sets a flag called *self-closing flag* on the token — and then the tree-construction stage, for HTML elements, simply does not act on that flag. It is acknowledged and discarded. That design is deliberate. HTML has never required end tags for a whole class of elements, and it has never allowed authors to invent which elements may be empty. Whether an element can have children is a property of the element itself, defined by the specification, not something the author decides per tag. ## Void elements The elements that never take an end tag are fixed and short: ```html <area> <base> <br> <col> <embed> <hr> <img> <input> <link> <meta> <source> <track> <wbr> ``` For these, writing `<br>` and `<br />` produces exactly the same DOM. Both are conforming — a validator accepts either. What is *not* allowed is an end tag: `</br>` and `</img>` are errors. (`</br>` has a legacy special case where the parser treats it as if you had written `<br>`; `</img>` is simply ignored, because a void element is never pushed onto the parser's stack of open elements, so there is nothing for the end tag to close.) So this markup: ```html <img src="a.png" alt="A">Hello</img> ``` yields an `img` element followed by a sibling text node `Hello`. The `</img>` produces a parse error and no DOM node. ## What happens on a non-void element Writing `<div />` triggers the spec's parse error named *non-void-html-element-start-tag-with-trailing-solidus*. "Parse error" in HTML never means "stop": it means the specification prescribes exactly what to do next, and here the prescription is to ignore the slash. The div is opened and pushed onto the stack of open elements, so subsequent markup nests inside it: ```html <div class="spacer" /> <p>This paragraph is a CHILD of the div, not a sibling.</p> ``` The div closes only when a real `</div>` appears, when an ancestor's end tag pops through it, or at end of file. Custom elements behave the same way. `<my-widget />` is an ordinary HTML element with a hyphenated name; the slash does nothing and the widget swallows the rest of the document until `</my-widget>`. ## The `<script>` trap This one ships in real code: ```html <script src="analytics.js" /> <h1>Title</h1> ``` After the script start tag the tokenizer switches into *script data* state, where markup is no longer markup — it is script text — until a matching `</script>` is found. The `<h1>` never becomes an element; it becomes characters inside the script element's text. `analytics.js` will still load once an end tag eventually arrives, but a chunk of the page has silently vanished from the DOM. The same reasoning applies to `<textarea />`, `<title />` and `<style />`, whose contents are also tokenized in special states. ## Where the slash is real: foreign content Inside an `<svg>` or `<math>` subtree the parser runs foreign-content rules, and there the self-closing flag *is* honoured: ```html <svg viewBox="0 0 10 10"> <circle cx="5" cy="5" r="4" /> </svg> ``` The circle really is closed by the slash. This is why copy-pasted SVG, which is written in XML style, parses correctly when pasted straight into an HTML page — and why people generalise the rule to HTML and get bitten. ## What to say in an interview Say that HTML decides emptiness per element, not per tag; name a few void elements; state that the slash is tolerated and ignored on HTML elements, honoured in SVG/MathML; and give the `<div />` or `<script />` consequence. That last part is what separates a memorised rule from understanding the parser.
- What does the parser do with the text in `<img src="a.png" alt="A">Hello</img>`?You get an `img` element and then a sibling text node `Hello`. A void element is never pushed onto the stack of open elements, so `</img>` has nothing to close: it is a parse error and is discarded. The text was never inside the image, because an image cannot have children at all.
- Does the trailing slash close a custom element such as `<my-widget />`?No. A custom element is an ordinary HTML element with a hyphenated name, so the slash is ignored and the element stays open. Everything after it becomes its children until `</my-widget>` or an ancestor's end tag pops it. Custom elements must always be written with an explicit end tag.
- If the slash is ignored anyway, is writing `<br />` wrong?No — it is conforming. The specification explicitly permits a trailing slash on a void element's start tag, so validators accept both `<br>` and `<br />`. It is a style choice, usually a habit carried over from XHTML or from tooling that formats markup in XML style. The risk is only in generalising it to non-void elements.
saying these in an interview costs you the question
- Claims <div /> closes the div the way JSX does
- Thinks <br> without the slash is invalid HTML
- Says <script src="x.js" /> is a valid empty script tag
- Believes the parser reports an error for a stray slash
- Assumes any element may be made empty by the author