skip to content

Document Structure

How a page is assembled before anything renders: the doctype, the head/body skeleton, how the parser builds a tree out of imperfect markup, where scripts go, and the attributes available on every element. Interviewers use this to see whether you understand what the browser does with your file, not just what it looks like.

part ofHTMLoverview, primer and where to startread it →
on this pageshow

explore

questions

26

What does the line <!DOCTYPE html> at the top of an HTML file do, and what happens if you leave it out?

level: juniorimportance: must knowfreq 72%

answer

  1. not a tag, a switch
  2. no DTD behind the modern one
  3. two layout personalities per browser
  4. missing it means legacy box model
  5. document.compatMode reports which

basics

~20 s
<!DOCTYPE html> puts the browser in standards mode, where layout follows current specifications. It references no DTD and validates nothing. Without it the page renders in quirks mode, which emulates legacy browser behaviour — most visibly a different box model.

solid answer

~50 s

`<!DOCTYPE html>` is not a tag and not a version declaration — it is a switch. Its only job is to tell the browser to render the document in **standards mode** (the spec calls it *no-quirks mode*) rather than **quirks mode**, which reproduces pre-standards browser behaviour so that ancient pages still look right. Unlike the old HTML 4.01 and XHTML 1.0 doctypes it points at no DTD, and nothing about it makes the browser validate your markup or parse it differently — the HTML parser is the same either way. Leave it out and you get quirks mode: `width` starts including padding and border, percentage heights resolve where they should not, and a handful of other legacy rules kick in. You can confirm which mode you got with `document.compatMode`, which returns `"CSS1Compat"` for standards and `"BackCompat"` for quirks.

go deeper

for a junior

Be able to say the one line does one thing: it selects standards mode. Know that leaving it out gives quirks mode and that the most visible symptom is boxes sizing differently.

for a middle

Explain that the doctype is a mode switch consumed by the parser, name the three modes, and describe the box-model difference concretely with numbers. Be ready to say what the doctype does not do — no validation, no parser change.

for a senior

Show you can diagnose it in a running system: check document.compatMode, remember that mode is per document so iframes and injected fragments switch independently, and know which legacy behaviours quirks mode restores.

for a principal

Frame it as backward-compatibility policy: browsers keep two layout engines forever because the web is append-only. Be ready to discuss the cost of that decision and how you would prevent quirks mode from reappearing in server-rendered or templated output.

## It is a mode switch, not a version tag `<!DOCTYPE html>` looks like markup but it is not an element: it has no content, no closing tag, and it never appears in the DOM as an element (it is exposed as `document.doctype`). It is a preamble the parser consumes before anything else, and in modern HTML its single purpose is to choose a **rendering mode**. The name is a leftover. In HTML 4.01 and XHTML 1.0 the doctype genuinely referenced a Document Type Definition — a grammar file: ```html <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> ``` Modern HTML is not defined by a DTD at all, so the doctype shrank to the shortest string browsers would still recognise as "this author knows about standards": ```html <!DOCTYPE html> ``` It is case-insensitive (`<!doctype html>` is identical) and must come before any content in the document. ## Why the switch exists at all When browsers began following the CSS specifications in the late 1990s, the web was already full of pages written against the *old* behaviour — especially a box model in which a declared `width` covered padding and border. Rendering those pages correctly would have broken them visually. So browsers kept both behaviours and used the doctype as the signal: a page that bothered to declare one was assumed to want the standards behaviour; a page with none was assumed to be legacy content. That compromise is permanent. Every browser still ships two layout personalities, and the doctype is how you pick. ## The three modes The HTML standard defines three: - **no-quirks mode** — everyday "standards mode". `<!DOCTYPE html>` (and the strict legacy doctypes) get you here. - **limited-quirks mode** — "almost standards mode", triggered by certain transitional legacy doctypes. Almost identical to no-quirks. - **quirks mode** — no doctype, a misspelled one, or one of an explicit list of very old public identifiers. Any XML document — real XHTML served as `application/xhtml+xml` — is always in no-quirks mode regardless of its doctype, because the doctype switch is an HTML-parser rule. ## What you actually lose in quirks mode The headline difference is the box model. In standards mode a declared `width` is the width of the content box, and padding and border are added on top. In quirks mode the declared `width` swallows padding and border, so a 300px-wide box with 20px padding is 300px wide overall instead of 340px. Every layout calculation in a stylesheet written for one model comes out wrong in the other. Beyond that, quirks mode resolves percentage heights against ancestors that standards mode considers auto-height, accepts CSS lengths written without a unit and hex colours written without a `#`, and changes how a line box containing only an image is sized. None of these are things you want; they exist purely to keep old pages alive. ## What the doctype does *not* do This is where interviews separate memorised answers from understood ones: - It does **not** validate your markup. Validation is something you run in a separate tool; browsers never refuse malformed HTML. - It does **not** select a parser or an HTML "version". There is one HTML parser, and it tokenises the same bytes the same way whether the doctype is present, absent, or from 1997. Only layout rules change. - It does **not** affect which CSS or JavaScript features exist. Grid, flexbox, custom properties and modern JS all work in quirks mode. The engine is not older; a small set of layout rules is. - It does **not** apply to the page's subframes. Mode is a per-document property, so an `<iframe>` whose own document lacks a doctype is in quirks mode even inside a standards-mode parent. ## Checking at runtime ```js document.compatMode; // "CSS1Compat" = standards, "BackCompat" = quirks ``` The odd name `CSS1Compat` is historical; it does not mean the page is limited to CSS1. Note that limited-quirks mode also reports `"CSS1Compat"`, so the property distinguishes quirks from everything else rather than telling you all three modes apart. ## What to do in practice Write `<!DOCTYPE html>` as the first line of every HTML document you author, including partials that a server assembles into a full page and any HTML you inject into an `<iframe>` or a standalone email preview. It costs fifteen characters and removes an entire class of "why is this box the wrong size" bugs.

  • Does the doctype change how the browser parses your HTML?
    No. There is a single HTML parser and it tokenises the same bytes identically with or without a doctype — unclosed tags, implied elements and error recovery all behave the same. The doctype only sets the document's rendering mode, which affects layout rules, not tree construction. It also never validates: browsers happily render markup no validator would accept.
  • Why does the modern doctype not include a DTD URL like the HTML 4.01 one did?
    Because HTML is no longer defined by a DTD. The old public and system identifiers described an SGML grammar; today's HTML has a prose specification and an explicitly defined parsing algorithm instead. Browsers never fetched those DTD URLs to render pages anyway — they only pattern-matched the identifier string to pick a mode — so the doctype was reduced to the shortest string that still triggers standards mode.
  • If a standards-mode page embeds an iframe whose document has no doctype, what mode is the iframe in?
    Quirks mode. The rendering mode is a property of each document, not of the browsing context or the page as a whole, so the embedded document is switched independently by its own doctype. This is a common source of "the widget looks fine standalone but its boxes are the wrong size when embedded" — check `document.compatMode` inside the frame, not on the parent.

saying these in an interview costs you the question

  • Says the doctype tells the browser which HTML version to parse
  • Claims the doctype makes the browser validate the markup
  • Thinks quirks mode disables modern CSS like flexbox or grid
  • Believes the modern doctype still downloads a DTD file
  • Assumes rendering mode is per page rather than per document

context

open as a page

In HTML, what does the data-* attribute family give you that inventing your own attribute such as userid does not?

level: juniorimportance: must knowfreq 62%

basics

~20 s

data-* is HTML's sanctioned slot for custom data: it is valid markup, it can never collide with an attribute the language adds later, and browsers expose it to scripts through element.dataset. An invented attribute such as userid gets none of those guarantees.

open as a page

Why must <meta charset="utf-8"> appear at the very start of an HTML page's <head>, and what goes wrong if it comes later?

level: juniorimportance: must knowfreq 66%

basics

~20 s

Browsers pre-scan only the first 1024 bytes of an HTML file for the encoding declaration, so <meta charset="utf-8"> must come first inside <head>. Declared later, the browser guesses an encoding and may have to reparse the document or render garbled text.

open as a page

In HTML, how do a plain <script src>, a <script defer src>, and a <script async src> differ in when the file is downloaded, when it executes, and whether execution order is guaranteed?

level: juniorimportance: must knowfreq 85%

basics

~20 s

A plain <script src> pauses HTML parsing to download and run. defer downloads in parallel and runs after parsing, in document order. async downloads in parallel and runs the moment it arrives, in unpredictable order.

open as a page

What does the lang attribute on the <html> element actually change in a browser, and when should you set lang on an element deeper in the page?

level: middleimportance: must knowfreq 54%

basics

~20 s

lang declares the document's natural language with a BCP 47 tag, and it drives screen-reader pronunciation and voice choice, hyphenation and line breaking, font and glyph selection, the spellcheck dictionary, and translation offers. Set it again on any element whose content is in a different language.

open as a page

Why does a <link rel="stylesheet"> in the <head> delay a page's first paint, and what changes when you add media="print" to it?

level: middleimportance: must knowfreq 68%

basics

~20 s

A stylesheet linked in <head> is render-blocking: the browser will not paint until it has downloaded and parsed that CSS, so it never shows unstyled content. Adding media="print" still downloads the file, at lower priority, but stops it from blocking the first paint.

open as a page

Given the HTML `<p>Intro <div>Block</div></p>`, what DOM does the browser build, and why is the div not a child of the p?

level: middleimportance: must knowfreq 55%

basics

~20 s

A p element cannot contain a div, so the div's start tag implicitly closes the open p. The DOM becomes a p holding "Intro", a sibling div holding "Block", and an empty p created by the now-stray end tag.

open as a page

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?

level: juniorimportance: should knowfreq 50%

basics

~20 s

In 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.

open as a page

What concrete layout differences does a browser's quirks mode produce compared with standards mode?

level: middleimportance: should knowfreq 44%

basics

~20 s

Quirks mode restores legacy layout rules: a declared width includes padding and border, percentage heights resolve against ancestors standards mode treats as auto, unitless CSS lengths and hashless hex colours are accepted, and a line box holding only an image loses its descender gap.

open as a page

In HTML, how do data-* attribute names map onto keys of an element's dataset property, and what type do you get back when you read one?

level: middleimportance: should knowfreq 52%

basics

~10 s

dataset drops the data- prefix and converts each hyphen-plus-lowercase-letter into a capital, so data-user-id is read as dataset.userId. Every value read back is a string, never a number, boolean or object.

open as a page

A team hides table rows with the HTML hidden attribute, but rows carrying a class whose stylesheet rule sets display: flex stay visible. Why does hidden stop working, and what is the fix?

level: middleimportance: should knowfreq 42%

basics

~20 s

The hidden attribute is not a rendering switch — browsers implement it with a user-agent stylesheet rule that sets display: none. Any author rule setting display on the same element outranks the user-agent origin and un-hides it. The fix is a stronger author rule or a state class that controls display.

open as a page

HTML requires the id attribute to be unique within a document. What actually breaks when two elements end up with the same id?

level: middleimportance: should knowfreq 46%

basics

~20 s

Nothing throws — every lookup that resolves an id to one element silently takes the first in tree order, so getElementById, fragment links and attributes that reference an id all point at the first match while selector matching still matches all of them, which is what hides the bug.

open as a page

You write `<table><tr><td>1</td></tr></table>` with no `<tbody>` in the source. What does the parsed DOM contain that your markup does not, and why?

level: middleimportance: should knowfreq 45%

basics

~20 s

The parser inserts a tbody element for you, so the DOM is table > tbody > tr > td. A row start tag inside a table implies a tbody start tag, which means table rows are never direct children of the table element.

open as a page

In an HTML page, what actually changes if you move <script src="app.js"> from just before </body> into <head> and add the defer attribute?

level: middleimportance: should knowfreq 50%

basics

~20 s

The download starts earlier, because the parser discovers the tag at the top instead of at the bottom. Execution timing barely moves: both forms run after the markup exists and before DOMContentLoaded, but the deferred one waits for the complete document.

open as a page

How does <script type="module"> differ from a classic <script src> in when it executes, and what does adding the async attribute to a module script change?

level: middleimportance: should knowfreq 55%

basics

~20 s

A module script is deferred by default: it downloads in parallel and executes after the document is parsed, in document order, before DOMContentLoaded. Adding async makes it run as soon as it is ready, and async works on inline modules too.

open as a page

A production page renders in quirks mode even though the source appears to start with <!DOCTYPE html>. How do you confirm the mode and track down the cause?

level: seniorimportance: should knowfreq 30%

basics

~20 s

Confirm with document.compatMode: "BackCompat" means quirks mode. Then inspect the raw response body rather than the DevTools element tree, looking for non-whitespace output emitted before the doctype, a misspelled or legacy doctype, and remember that iframes and injected documents carry their own mode.

open as a page

What does the HTML inert attribute do to the subtree it is set on, and which bug does it fix that hiding the background visually or with aria-hidden does not?

level: seniorimportance: should knowfreq 38%

basics

~20 s

inert makes an element and everything inside it non-interactive: the subtree cannot be focused by Tab or programmatically, does not respond to clicks, is not selectable or findable by find-in-page, and is hidden from assistive technology. It fixes background content behind a modal that is dimmed but still reachable by keyboard.

open as a page

An HTML page's <head> contains a stray <div> before its <meta> and <link> tags. What does the parser do at that point, and what stops working?

level: seniorimportance: should knowfreq 30%

basics

~20 s

Only a fixed set of elements may appear in <head>. On reaching a <div> the parser implicitly closes <head>, opens <body>, and puts the div and everything after it in the body — so metadata written later is no longer in the head, and a late encoding declaration is missed.

open as a page

A templating partial ships a `<div>` whose end tag is missing. HTML has no fatal parse errors — what does the browser do with the markup that follows, and how would you catch this class of bug before release?

level: seniorimportance: should knowfreq 40%

basics

~20 s

Nothing fails. The div stays on the parser's stack of open elements, so following markup becomes its descendants until an ancestor's end tag or end of file closes it implicitly. Catch it by validating rendered pages in CI, not by eye.

open as a page

Why is a third-party snippet that calls document.write() from a <script> tag a problem for HTML page loading, and what happens if the same call runs after the document has finished parsing?

level: seniorimportance: should knowfreq 35%

basics

~20 s

document.write() injects markup at the parser's current position, so the parser must stop and tokenise it — and any script it injects blocks the parser again. After parsing has finished, the same call implicitly reopens the document and wipes the existing page.

open as a page

Browsers have a third rendering mode between standards and quirks — what is almost-standards (limited-quirks) mode, what triggers it, and what does it change?

level: middleimportance: nice to knowfreq 18%

basics

~20 s

Almost-standards mode, called limited-quirks mode in the HTML standard, is triggered by transitional legacy doctypes such as XHTML 1.0 Transitional. It matches standards mode except for one rule: a line box containing only images is sized to the images, removing the descender gap under an inline image.

open as a page

What does the HTML <base href="..."> element change on a page, and why must it appear before any other element carrying a URL?

level: middleimportance: nice to knowfreq 24%

basics

~20 s
<base href> sets the document base URL against which every relative URL on the page resolves — links, images, scripts, form actions and even fragment links like #top. Only the first <base href> counts, and URLs parsed before it has been seen resolve against the old base.
open as a page

How does the HTML parser treat markup inside an inline `<svg>` element differently from ordinary HTML, and what happens if a `<p>` start tag appears inside it?

level: middleimportance: nice to knowfreq 28%

basics

~20 s

Inside <svg> the parser switches to foreign-content rules: a trailing slash genuinely self-closes an element, and known attribute names are case-corrected to spellings such as viewBox. A <p> start tag forces a breakout, popping the parser back into HTML.

open as a page

What does the nomodule attribute on an HTML <script> tag do, and how does pairing it with <script type="module"> let one page serve two different bundles?

level: seniorimportance: nice to knowfreq 25%

basics

~20 s

nomodule tells any browser that supports ES modules to skip that script. Paired with a type="module" tag, modern browsers run the module bundle and ignore the fallback, while older engines ignore the unknown module type and run the nomodule one.

open as a page

You inherit a large legacy application whose pages render in quirks mode. How do you plan the move to standards mode, and what would you tell stakeholders about the risk?

level: principalimportance: nice to knowfreq 14%

basics

~20 s

Treat it as a per-document migration, not a one-line change. Because rendering mode is set per document, migrate route by route behind visual regression coverage, prioritise pages whose stylesheets depend on the legacy box model and percentage heights, and expect layout numbers to shift on every page you switch.

open as a page