Skip to content
academia.sh

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-equiv declarations 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.

Start typing to search.

↑↓ Esc navigate · open · close