HTML File Documentation


Summary

An HTML (HyperText Markup Language) file is a plain-text document that a web browser parses into a page: headings, paragraphs, images, links and forms. It is defined by the WHATWG HTML Living Standard (HTML5 baseline, 2014) and served with the MIME type text/html. The .html and .htm extensions are the identical format; the three-letter form survives only from the old DOS 8.3 filename limit.

Technical details

FeatureValue
Full nameHyperText Markup Language document
File extension.html, .htm
MIME typetext/html (XHTML: application/xhtml+xml)
Format typePlain-text markup, tag-based nested elements
Character encodingUTF-8 recommended; declared via <meta charset> or HTTP header
DeveloperWHATWG and W3C; originated by Tim Berners-Lee at CERN
Introduced1991 (first HTML); HTML5 baseline from 2014
Latest versionHTML Living Standard (WHATWG, continuously updated)
Standard / specWHATWG HTML Living Standard; historically HTML 4.01, XHTML 1.0/1.1, HTML5 (W3C Rec. 2014)
Open standardYes — royalty-free
ContainerPlain text (optional UTF-8 BOM EF BB BF at offset 0)
CompressionNone in the file; servers may gzip/Brotli in transit
Document tree<html><head> + <body>
ScriptingJavaScript via <script>; styling via CSS <link>/<style>
Doctype<!DOCTYPE html> (HTML5, triggers standards mode)
Magic numberNone (text); files usually begin <!DOCTYPE html> or <html
Related extensions.htm, .xhtml, .mhtml, .css, .js, .xml
Specificationhtml.spec.whatwg.org
Structure at a glance

HTML is plain UTF-8 text with no file signature. A document opens with the <!DOCTYPE html> declaration, then a single root <html> element containing exactly one <head> (metadata: <title>, <meta charset>, links to CSS and JS) and one <body> (the visible content). Content is marked up with elements written as a start tag, content, and end tag (<p>…</p>); attributes add data as name="value" pairs inside the start tag. Some elements are void (<img>, <br>) and take no end tag.

What is an HTML file?

HTML stands for HyperText Markup Language. An .html file is a plain-text document that describes the structure and content of a web page using markup: text wrapped in angle-bracket tags that a browser interprets rather than prints. Tim Berners-Lee wrote the first version at CERN in 1991; the language is now maintained as the HTML Living Standard by the WHATWG, with the HTML5 baseline dating from the W3C Recommendation of 2014. The file itself is nothing more than characters in some encoding: a browser reads those characters, builds an in-memory model of the page, and paints the result. Its MIME type is text/html.

The .html and .htm extensions name the identical format. The shorter spelling is a relic of the DOS/Windows “8.3” filename rule, which capped extensions at three characters; Unix and the web used the four-letter form. Servers deliver both as text/html and browsers treat them the same, so renaming one to the other changes nothing. Everything below is about what the characters inside the file actually mean.

The doctype and the parser’s rendering modes

A well-formed HTML5 document begins with a document type declaration:

<!DOCTYPE html>

In HTML5 this is not a reference to a Document Type Definition, as it was in HTML 4 and XHTML (which carried long public identifiers and DTD URLs). It is a near-empty token whose only job is to switch the parser into no-quirks mode (often called standards mode). Its presence or absence changes how the browser lays out the page: without a recognised doctype the parser drops into quirks mode, reviving legacy behaviours such as the old Internet Explorer box model and looser table rules, for backward compatibility with pages written in the 1990s. The doctype is case-insensitive and must be the first thing in the document, before any element.

The document tree: html, head and body

Below the doctype, an HTML document is a single tree with one root element, <html>. That root has exactly two children: <head> and <body>.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Document title</title>
    <link rel="stylesheet" href="style.css">
  </head>
  <body>
    <h1>A heading</h1>
    <p>A paragraph with a <a href="/">link</a>.</p>
    <script src="app.js"></script>
  </body>
</html>

The <head> holds metadata that never renders as page content: the document <title>, the character-encoding declaration, <meta> tags, and references to external resources such as CSS stylesheets (<link>) and JavaScript (<script>). The <body> holds everything the reader sees. A striking property of HTML is that this structure is largely optional in the source text: the parser will infer a missing <html>, <head> or <body>. A file containing only <p>Hello</p> still produces a complete tree with all three implied. The tags are how you write the document; the tree is what the browser builds.

Elements versus attributes

An element is the unit of markup. Most elements are written as a start tag, some content, and an end tag: <p>text</p>. Elements nest to form the tree, and the nesting must be consistent. Attributes live inside the start tag as name="value" pairs and configure the element: the href on an <a> anchor sets its destination, the src and alt on an <img> set its source and text alternative. Attribute values may be quoted with double or single quotes, or left unquoted when they contain no spaces or special characters. Boolean attributes such as disabled or required need no value; their mere presence is the true state.

Some attributes are global and apply to any element, including id (a unique identifier), class (space-separated names used by CSS selectors and scripts), style (inline CSS), and the data-* family for custom data. Element and attribute names are case-insensitive in the HTML syntax, though lowercase is the convention.

Void, raw-text and normal elements

Not every element follows the start-tag/content/end-tag pattern. HTML defines a fixed set of void elements that have no content and therefore no end tag: area, base, br, col, embed, hr, img, input, link, meta, source, track and wbr. Writing <img src="x.png"> is complete; there is no </img>. The trailing slash of <br /> is permitted but has no effect in HTML (it matters only in XML-based XHTML).

A second special category is raw-text elements, namely <script> and <style>. Inside them the parser does not look for child tags; it reads characters literally until it sees the matching closing tag. That is why a < inside JavaScript does not start an element, and why the string </script> must not appear mid-script even inside a quoted string. <textarea> and <title> are escapable raw-text: they take literal text but still honour character references.

Character references and entities

Because <, > and & are syntactically meaningful, HTML provides character references to include them as literal text. There are three forms:

FormExampleResult
Named&amp;, &lt;, &copy;&, <, ©
Decimal numeric&#169;©
Hexadecimal numeric&#x2014;

Named references (also loosely called entities) map a name to a code point; the HTML standard defines a fixed list of them, and most, for historical reasons, must end in a semicolon. Numeric references address any Unicode code point directly by its number. The ampersand always begins a reference, so to write a literal ampersand you encode it as &amp;. In normal text you only strictly need to escape & and <; inside attribute values you also escape the quote character in use.

Character encoding and the charset declaration

An HTML file is bytes, and the browser must know which encoding maps those bytes to characters before it can build text correctly. The HTML standard recommends UTF-8 and requires the document to declare its encoding. The declaration is a <meta> element in the head:

<meta charset="utf-8">

To make this work the parser uses a bootstrap rule: it begins reading in a fallback encoding, and the charset declaration must appear within the first 1024 bytes of the file so that, once found, the parser can restart with the correct encoding before it has consumed any real content. An HTTP Content-Type header takes precedence over the meta tag, and a UTF-8 byte-order mark (EF BB BF) at offset 0, if present, overrides both. Getting this wrong is the classic cause of mojibake: text that displays as garbled accented characters because it was decoded with the wrong encoding.

The parser: tokenizer and tree construction

Turning the byte stream into a page happens in two coupled stages defined precisely by the standard. The tokenizer is a state machine that scans the character stream and emits tokens: start tags, end tags, comments, doctype, and runs of character data. It is the tokenizer that knows a < begins a tag, that <!-- begins a comment, and that inside a <script> the rules change so that markup is not recognised.

The tree construction stage consumes those tokens and builds the node tree, applying HTML’s forgiving rules. This is where implied elements are inserted, where a stray or misnested tag is corrected, and where the “list of active formatting elements” reconstructs bold or italic across badly nested spans. HTML parsing is defined to never fail: any byte sequence produces some tree, which is why browsers render broken pages instead of throwing an error. This is the opposite of XML, where a single unclosed tag is a fatal well-formedness error. The forgiving model is also why two parsers, following the same specified algorithm, produce the same tree from the same malformed input.

From tree to DOM

The tree the parser builds is the Document Object Model (DOM): a live, in-memory object graph of nodes, one per element, attribute, text run and comment, rooted at the document node. The DOM is the interface between the parsed markup and everything dynamic. CSS is matched against DOM nodes to compute their styles; JavaScript reads and mutates the DOM through APIs such as document.querySelector and element.appendChild, and every change re-renders the affected part of the page. Scripts also run during parsing: a <script> without async or defer blocks the parser, executes immediately, and can even write into the token stream, which is why script placement affects load behaviour.

One practical consequence follows directly from this: a local .html file, when opened in a browser, executes any JavaScript it embeds, exactly as a page fetched from a server would. The browser does not distinguish “from disk” from “from the web” when running scripts, so opening an unknown HTML file runs its code in your browser. Server-generated pages, including those emitted by PHP, are just HTML text by the time they reach the browser; the DOM is built the same way regardless of what produced the markup.

Semantic elements and document outline

HTML5 added a set of semantic elements that name the role of a region rather than just its appearance: <header>, <nav>, <main>, <article>, <section>, <aside> and <footer>. They replace the older habit of using generic <div> containers with class names for the same purpose. The distinction is not cosmetic: semantic elements carry meaning that assistive technologies expose (a screen reader can jump to the <nav> or the <main> content), that search engines read, and that maps onto the accessibility tree the browser builds alongside the DOM. Headings <h1> through <h6> establish the document’s outline, and the semantic sectioning elements group content under them.

Frequently asked questions

Is there any technical difference between .html and .htm?

No. They are byte-for-byte the same format. The .htm spelling exists only because early DOS and Windows file systems limited extensions to three characters. Servers send both with the text/html MIME type and browsers parse them identically, so you can rename one to the other freely.

Why does leaving out the doctype change how my page looks?

An absent or unrecognised doctype puts the browser into quirks mode, which revives legacy layout behaviour such as the old box model for backward compatibility with pre-standards pages. Adding <!DOCTYPE html> as the first line switches the parser to no-quirks (standards) mode, where modern CSS layout rules apply.

Why do accented characters turn into garbage in my HTML file?

The browser decoded the bytes with the wrong character encoding. Save the file as UTF-8 and declare it with <meta charset="utf-8"> within the first 1024 bytes of the head. If the server sends a conflicting Content-Type charset, that header wins over the meta tag.

References