Lesson 07 / 25
Meta Tags
How the charset declaration decides byte interpretation, the priority of sources that determine encoding, the viewport declaration, and named metadata.
Contents
The previous lesson made an assumption while resolving character references: which rule bytes were turned into characters by was already known. This lesson lifts that assumption and takes up the metadata tags in the head section, starting with the most decisive one.
The meta element is a void element and carries no meaning on its own; what carries meaning
is its attributes. It is used in four separate functions, and these are independent of one
another.
The Charset Declaration
The Character Encodings lesson in the How Computers Work course established a single point: a byte sequence does not say, on its own, which rule it was written with. The same bytes resolve to different characters under different rules.
// charset.mjs — same bytes, two separate encoding assumptions // The measured text is kept in Turkish on purpose: the lesson measures the exact // byte pattern (c4 b1) of the letter "ı", which has no equivalent in English. const text = "Sıcaklık: -4 °C"; const bytes = Buffer.from(text, "utf8"); const codePoints = (d) => [...d].map((k) => "U+" + k.codePointAt(0).toString(16).toUpperCase().padStart(4, "0")).join(" "); console.log("bytes :", bytes.toString("hex").match(/../g).join(" ")); console.log("byte count :", bytes.length); console.log("char count :", text.length); console.log("utf-8 reading :", bytes.toString("utf8")); console.log("latin1 reading :", bytes.toString("latin1")); console.log("utf-8 first 3 :", codePoints(bytes.toString("utf8").slice(0, 3))); console.log("latin1 first 5 :", codePoints(bytes.toString("latin1").slice(0, 5))); console.log("--- the charset declaration is searched for in the document's first bytes ---"); const head = '<!doctype html>\n<html lang="en">\n<head>\n<meta charset="utf-8">\n'; console.log("byte declaration ends at:", Buffer.byteLength(head)); console.log("under 1024 bytes :", Buffer.byteLength(head) < 1024);
bytes : 53 c4 b1 63 61 6b 6c c4 b1 6b 3a 20 2d 34 20 c2 b0 43 byte count : 18 char count : 15 utf-8 reading : Sıcaklık: -4 °C latin1 reading : Sıcaklık: -4 °C utf-8 first 3 : U+0053 U+0131 U+0063 latin1 first 5 : U+0053 U+00C4 U+00B1 U+0063 U+0061 --- the charset declaration is searched for in the document's first bytes --- byte declaration ends at: 63 under 1024 bytes : true
The byte pair c4 b1 resolves to a single character under one rule (U+0131, ı); under
another rule, to two separate characters (U+00C4 and U+00B1). The bytes are the same; only
the interpretation differs. Eighteen bytes give fifteen characters under the first reading,
eighteen under the second.
The document’s own declaration is a single line:
<meta charset="utf-8">
This line’s effect is not visual, it is structural. If the declaration is wrong, it is not just a few characters that break; the document resolves into an entirely different character sequence, and even tag names can be affected.
Why the Declaration’s Place Matters
There is a circular problem here. The declaration itself is inside the document; reading it requires decoding the document, and decoding requires reading the declaration.
The solution is a pre-scan. The parser scans the document’s first section — the defined limit
is 1024 bytes — with a single-byte assumption and looks only for a charset declaration. If
it finds one, it starts parsing the document with that rule.
This has two consequences. First, the declaration has to be within the first 1024 bytes; this is why it is written at the very start of the head section. Second, if the declaration falls outside this limit or is not found during the pre-scan with the default rule, the parser has already started with the wrong rule; once it sees the declaration later, it has to redo parsing from the start. This restart is a measurable cost, and it is avoided by the declaration’s placement.
Sources That Determine Encoding
The meta declaration in the document is not the only source. There is an ordered priority
list.
| Priority | Source |
|---|---|
| 1 | Byte order mark (BOM) |
| 2 | The user’s explicit choice |
| 3 | Transport layer: the charset in the HTTP Content-Type header |
| 4 | The meta charset declaration in the document |
| 5 | Sniffing and default |
The byte order mark concept was defined in the Byte Order lesson of the How Computers Work course; a few bytes at the start of the document state the encoding and override everything else.
The third rank deserves attention: the HTTP header overrides the document’s declaration.
The HTTP Request and Response lesson in the How the Internet Works course showed that the
Content-Type header carries a charset parameter. That parameter applies even if the
document carries a different declaration. If the server configuration and the document
conflict, the server wins; this is a frequent reason why characters that look broken are
searched for in the document and not found.
The fifth rank is not a guarantee. Sniffing makes a guess by looking at the document’s content, and the guess can be wrong. Not writing the declaration means leaving the result to the environment.
The Viewport Declaration
The second use of meta declares how the document will scale on narrow screens.
<meta name="viewport" content="width=device-width, initial-scale=1">
This declaration’s reason is historical. Narrow-screen devices assume a wide virtual viewport to keep documents not written for a narrow screen readable, and shrink the page. The declaration turns off this assumption: the viewport’s width is taken as the device’s own width, and the initial scale is one.
The declaration itself is not a presentation decision; it decides which width the presentation layer will compute against. For this reason it is present in every document that accounts for narrow screens, and it is the precondition for the responsive layout covered in the next course.
Values that turn off scaling, like user-scalable=no, can be written. They should not be:
zooming in is the only access path for users with limited vision, and turning it off is an
accessibility violation.
Named Metadata
The third use declares information about the document with a name/content pair. This
information is not painted; it is carried for programs that process the document.
<meta name="description" content="Temperature, relative humidity, wind speed, and precipitation records from the North Slope automated measurement station."> <meta name="robots" content="index, follow"> <meta name="author" content="Measurement Network Working Group">
The description value can be used as the document’s summary shown in search results. It is
not guaranteed to be used — indexers can choose to produce a more suitable summary from the
document’s content. Writing it is still justified: when it is not written, the choice is left
entirely to the indexer.
The robots value tells indexers whether the document should be indexed and whether its links
should be followed. This is not an access control; a client that does not follow the
declaration still reads the document. Content requiring privacy is protected with
authorization, not with metadata.
There are separate metadata contracts for systems that preview the document in other
environments; these use the same meta mechanism and declare fields like title, description,
and image address. Contract names vary from platform to platform; what is common is that the
preview is explicitly declared instead of being guessed from the document’s content.
Equivalent Headers
The fourth use declares the equivalent of an HTTP response header with the http-equiv
attribute.
<meta http-equiv="content-security-policy" content="default-src 'self'">
This mechanism is for situations where there is no way to change the server’s headers. If
there is a way, the real header is preferred: the header applies before the document is
parsed, the http-equiv declaration only once the parser reaches it. This difference is
decisive for security declarations.
The Station Document’s Head Section
The head section of the document developed throughout the course becomes this:
<head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>North Slope Measurement Station — Measurement Network</title> <meta name="description" content="Temperature, relative humidity, wind speed, and precipitation records from the North Slope automated measurement station."> </head>
The order is not incidental: the encoding declaration comes first, because it decides how
everything after it will be read. The title element, as noted in the previous lesson, names
the document outside its context, and here it also carries the site’s name.
Summary
- The charset declaration says which rule bytes will be converted to characters by; a wrong declaration resolves the whole document into a different character sequence.
- Because of the parser’s pre-scan, the declaration has to be within the first 1024 bytes; being found late means parsing has to be redone from the start.
- Sources that determine encoding have a priority, and the HTTP header overrides the document’s declaration.
- The viewport declaration decides which width the presentation layer computes against; values that turn off scaling break accessibility.
- Named metadata is for programs that process the document and is not binding; indexing declarations provide no access control.
http-equivdeclarations stand in for real HTTP headers but apply later; the header is preferred where possible.
Next Step
The head section is complete; next comes the body. The body’s first structural decision is headings: the tags that declare which sections the document is divided into and these sections’ level relative to one another. The next lesson shows why heading level is a structural declaration rather than a font size, and how skipping a level breaks the document’s outline.
To keep your progress and take notes, Log in
My notes
Log in to take notes.