Topic 6.1
The Head in Depth
In one line
The head holds information about the page: how to decode it (charset), how to size it on phones (viewport), where relative links point (base), and which styles and scripts to load, and where you place each of them changes how the page behaves.
Think of it like this
The label on a parcel. Before anyone opens the box, the label says what language the note inside is written in, which way is up, where to send replies and what else is coming in other boxes. The <head> is that label: the browser reads it first, and it shapes how everything inside the box is handled.
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- head
- The part of the page with information about it. Nothing in it is shown in the page itself.
- meta
- An element that states one fact about the page, like its character set or description.
- Character encoding
- The rule for turning stored bytes into letters. UTF-8 is the one to use.
- Viewport
- The area of the screen where the page is drawn. On a phone it is the whole screen width.
- CSS pixel
- The unit CSS sizes use. A phone may pack 2 or 3 real screen dots into one CSS pixel.
- Relative URL
- A link written without a domain, like
guide.html, worked out from the current page's address. - base
- An element that changes the starting address used for all relative URLs on the page.
- Parser
- The part of the browser that reads HTML text from top to bottom and builds the page's element tree.
- Render-blocking
- Something the browser must finish before it can show the page, like a stylesheet in the head.
Step by step
01Charset first
The browser starts decoding bytes immediately. Put the charset at the very top of the head so it is known before any text, including the title.
If the browser finds the charset late, it may have to throw away what it decoded and start again.
<head>
<meta charset="utf-8">02Then the viewport
The viewport line is the same on almost every site. Learn it by heart. Add viewport-fit=cover only if you design for the area under a notch and pad the edges with env(safe-area-inset-*) in CSS.
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">03Title, description and the rest of the facts
Next come the <title> and the <meta name="description"> (Topic 6.2), then social tags (6.3), icons (6.4) and SEO links like canonical (6.7).
<meta name="color-scheme" content="light dark"> tells the browser your page supports both themes, so default form controls and scrollbars follow the user's dark mode.
<title>Pancake recipes — Asha's Kitchen</title>
<meta name="description" content="Fluffy pancakes in 20 minutes, with egg-free and gluten-free versions.">
<meta name="color-scheme" content="light dark">04Styles and scripts
Stylesheets go in the head so the first paint is styled. Scripts go in the head with defer, so they download while the page is parsed and run once it is complete.
A plain script without defer pauses the parser right where it stands, as the diagram shows.
<link rel="stylesheet" href="/styles.css">
<script src="/app.js" defer></script>
</head>05The order that works
A safe, complete order: charset, viewport, title, description, social and SEO tags, icons, preconnects and preloads, stylesheets, deferred scripts. Only the charset position is a hard rule; the rest is a convention that makes heads easy to read and keeps the important bytes early.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Pancake recipes — Asha's Kitchen</title>
<meta name="description" content="Fluffy pancakes in 20 minutes.">
<link rel="canonical" href="https://example.com/pancakes">
<link rel="icon" href="/favicon.ico" sizes="32x32">
<link rel="stylesheet" href="/styles.css">
<script src="/app.js" defer></script>
</head>
<body>
<h1>Pancakes</h1>
</body>
</html>Try it yourself
- 1
Predict the head list
In the first example, add
<meta name="author" content="Asha">after the description. Before you press Run, predict which line the console adds and where. Then run it and check. - 2
Move the script
In the second example, move the whole
<script>block from the head to just before</body>. Predict the first line of the console, then run it. (Addingdeferto it would do nothing:deferonly works on scripts with asrc.) - 3
Change the base
In the third example, change the base to
https://example.com/docs/v2/. Predict all three printed URLs first. Then delete the<base>line: what do the URLs start with now? (The preview's own address isabout:srcdoc.)
Code & diagrams
The script walks through every element in the head and prints its tag and its key attribute.
Preview
Console
Nothing logged yet.Expected console output
meta charset=utf-8
meta name=viewport
title Head tour
meta name=description
meta name=color-scheme
link rel=iconThe head script runs while the parser is still in the head, so the heading doesn't exist yet. The JavaScript tab runs at the end of the body.
Preview
Console
Nothing logged yet.Expected console output
In the head, the heading is: null
At the end of the body, the heading is: <h1#title>`getAttribute` gives what you wrote; the `href` property gives the full URL the browser will really use. Notice the `#top` link now points at another page.
Preview
Console
Nothing logged yet.Expected console output
guide.html -> https://example.com/docs/guide.html
../about -> https://example.com/about
#top -> https://example.com/docs/#topBreak it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
Read the page from a head script
In the second example, change the head script to console.log(document.querySelector("h1").textContent);.
Break #2
Block zooming
Set the viewport to width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no and open the page on a phone.
Break #3
Fragment links under a base
Add <base href="https://example.com/"> to a page with a table of contents that uses <a href="#install">.
Myth vs fact
Myth
The order of tags in the head doesn't matter.
Fact
Most order is convention, but the charset must be in the first 1024 bytes, <base> must come before any URL it should affect, and a plain script blocks everything after it.
Myth
The viewport tag is only for responsive sites.
Fact
Without it every phone renders a pretend 980px-wide page and shrinks it. Even a simple text page needs it to be readable on a phone.
Myth
Putting scripts at the end of the body is the best practice.
Fact
It works, but defer in the head is better: the browser finds the script early and downloads it while parsing, instead of discovering it only at the end.
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
Browsers run a preload scanner: a light second parser that looks ahead for
srcandhrefURLs while the main parser is blocked by a script, so files start downloading early. Resources injected by JavaScript are invisible to it, which is one reason markup beats script-inserted tags for critical files. - ▸
Encoding detection order per the HTML standard: byte order mark, then the HTTP
Content-Typecharset, then a<meta charset>found by prescanning the first 1024 bytes, then guesses. Since HTML5,<meta charset>is the only valid encoding declaration for HTML pages, and the value should beutf-8. - ▸
A stylesheet in the head is render-blocking but not parser-blocking. However, a classic script that comes after a stylesheet waits for that stylesheet to load, because the script might read styles. So a slow CSS file can delay script execution too.
- ▸
<meta http-equiv>mimics HTTP headers (content-security-policy,refresh), but real headers are stronger: some directives, like CSP'sframe-ancestors, are ignored when set by meta.
Remember this
- 1
Only a few elements may live in the head:
<meta>(facts about the page),<title>(the tab text),<base>(the starting point for relative links),<link>(connections to other files, like stylesheets and icons),<style>(CSS written in the page),<script>(JavaScript),<noscript>(fallback content when scripts are off) and<template>(inert HTML for scripts to copy). Anything else, such as a<p>or<img>, makes the parser close the head early and move the element into the body, as you saw in Topic 0.4. - 2
<meta charset="utf-8">tells the browser how to turn the file's bytes into letters. A character encoding is that rule, and UTF-8 covers every language and emoji. It must appear within the first 1024 bytes of the file, so put it first in the head. If the server sends an encoding in itsContent-Typeheader, that header wins over the meta tag (a byte order mark at the start of the file beats both). - 3
<meta name="viewport" content="width=device-width, initial-scale=1">fixes how phones show your page. Without it, mobile browsers pretend the screen is about 980 CSS pixels wide and shrink the whole page to fit, so text becomes tiny.width=device-widthmakes the layout as wide as the phone's screen, andinitial-scale=1starts at 100% zoom. Other options exist:viewport-fit=coverlets the page draw under a phone's notch (then you pad with CSSenv(safe-area-inset-top)and friends), andinteractive-widget=resizes-contentasks the browser to shrink the layout when the on-screen keyboard opens (supported in Chromium-based browsers). Never addmaximum-scale=1oruser-scalable=no: they stop people from zooming, which fails accessibility guidelines for people with low vision. - 4
<base href="...">changes the starting point for every relative URL (a link likeguide.htmlthat doesn't start withhttps://). It can also set a defaulttarget, such as_blank. Only one<base>is allowed, and it must come before any element that uses a URL. It also affects#fragmentlinks, which then point at the base page instead of the current one, a classic bug. Most sites never need<base>. - 5
<link>connects the page to other resources. Itsrelattribute says how:stylesheet(CSS to apply),icon(the favicon),canonical(the main URL of this page),manifest,preload,preconnect,alternateand more. Each gets its own topic later in this phase.<style>holds CSS directly in the page, which is handy for small pages or for the few rules needed to draw the first screen. - 6
Script placement matters because a plain
<script>stops the HTML parser until the script has run. A script in the head therefore runs before the body exists, sodocument.querySelector("h1")returnsnullthere. The old fix was to put scripts at the end of the body; the modern fix is<script src="app.js" defer>in the head, which downloads in parallel and runs after the whole page is parsed (Topic 6.5 goes deeper). Styles belong in the head, so the first paint is already styled.
Explain it without notes
Which elements are allowed in the head, and what happens if you put a <p> there?
What does width=device-width, initial-scale=1 do, and why should you never add user-scalable=no?
Why does a plain script in the head see null when it looks for an element in the body, and how do you fix it?
What does <base> do, and what is the surprising effect on #fragment links?
Practice
Write a complete head for a page called Contact us — Green Leaf Café that sets UTF-8, the standard viewport, the title, a one-sentence description and a deferred script /js/contact.js.
A page has <base href="https://shop.example/en/">. What full URLs do cart, /help and ../fr/ resolve to?
Trade-offs
- ↔
Inlining a small
<style>in the head saves a request and speeds the first paint, but that CSS is downloaded again with every page instead of being cached once. - ↔
<base>can shorten many relative links, but it changes how every relative URL and fragment link behaves; on most sites root-relative URLs (/docs/…) are clearer.
Done when you can
I can list the elements allowed in the head.
I put
<meta charset="utf-8">first and know why.I can write the viewport tag from memory and know why zoom must stay enabled.
I know how
<base>changes relative and fragment links.I can explain why a plain head script can't see the body, and three ways to fix it.