HTML document and meta · 1 / 8
lesson 1

Anatomy of the head

What lives in the head, what blocks rendering, and the order that decides whether your page paints fast or slow.

~ 13 min read·lesson 1 of 8
0 / 8

The <head> is the part of your HTML the user never sees rendered. No paragraphs land here, no buttons appear. But everything in it shapes the page — the title in the browser tab, the favicon, the styles that decide how the body looks, the metadata that decides how the page is shared on Twitter.

It is also the part of your HTML that decides how fast your page paints. The browser parses the head before it shows anything; rules in the head can block the first paint or speed it up. Knowing what to put where pays off in performance.

What lives in the head

A short tour of what you find in a typical head, in roughly the order they appear.

  • <meta charset> — declares the file's character encoding. Always utf-8. Comes first, full stop.
  • <meta name="viewport"> — tells mobile browsers how to scale the page (covered in lesson 4).
  • <title> — the page title; shown in the tab and in search results.
  • <meta name="description"> — the description shown in search results.
  • <link rel="icon"> — the favicon.
  • <meta property="og:*"> — Open Graph tags for social previews.
  • <link rel="preconnect">, <link rel="preload"> — resource hints for performance (lesson 5).
  • <link rel="stylesheet"> — CSS files. Usually one or two, sometimes inlined.
  • <script> — JavaScript files (or inline scripts).
  • <link rel="manifest"> — web app manifest (lesson 6).
  • <script type="application/ld+json"> — structured data (lesson 8).

That is most of what you will ever write in a head. None of these elements render visible content; all of them shape how the body renders, or how the page presents itself when shared.

typical-head.html
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">

<title>Sourdough season is back · Daily Bread Bakery</title>
<meta name="description" content="Our wild-yeast loaf returns next Friday. Reserve a loaf or learn how the starter works.">

<link rel="icon" href="/favicon.svg" type="image/svg+xml">

<link rel="preconnect" href="https://images.example.com">
<link rel="stylesheet" href="/styles.css">

<meta property="og:title" content="Sourdough season is back">
<meta property="og:description" content="Our wild-yeast loaf returns next Friday.">
<meta property="og:image" content="https://example.com/loaf.jpg">
</head>

That head is reading-order: charset and viewport first, then title and description (the most important text), then the icon, then a preconnect, then the CSS, then the social tags. Each block has a job; the order has reasons covered below.

Blocking vs non-blocking

The browser parses HTML top to bottom. When it hits certain elements in the head, it pauses parsing or rendering until they finish. Those are render-blocking resources, and they decide your first-paint time.

The big two render-blockers:

<link rel="stylesheet"> — the browser will not paint the page until external CSS files load. (Otherwise it would have to repaint everything when CSS arrives, causing a flash of unstyled content.) This is mostly the right behavior — but it means a slow CSS request blocks your whole page.

<script> without defer or async — the browser stops parsing HTML to download and run the script. Body parsing is paused. Anything below the script does not appear until the script finishes.

Two attributes change script behavior:

  • <script defer src="..."> — fetch the script in parallel; run it after the HTML is fully parsed.
  • <script async src="..."> — fetch in parallel; run as soon as it arrives, blocking briefly when it does.

For most scripts in the head, defer is what you want. The script downloads while the rest of the HTML parses; nothing blocks; the script runs once the document is ready. async is right only for analytics and other order-independent scripts.

script-attrs.html
<head>
<!-- Blocks parsing until script downloads and runs -->
<script src="big-blocking.js"></script>

<!-- Downloads in parallel, runs after parsing — usually right -->
<script defer src="app.js"></script>

<!-- Downloads in parallel, runs ASAP — for analytics, etc. -->
<script async src="analytics.js"></script>
</head>

The first form (no attribute) is almost never what you want in the head. If you find a script tag with no defer or async, ask whether it could move to one or the other.

Tip

Inline <script> blocks (no src) ignore defer and async. They always run synchronously where they appear. Keep them small or move them to the end of the body.

check your understanding
You add <script src="app.js"></script> to the head, with no other attributes. The script is 200 KB. What's the effect on your page's first paint?

Order matters

A few rules of thumb for ordering elements within the head.

Charset comes first. Browsers may have already started decoding the file with a default charset before they see your <meta charset>. The earlier in the file, the better — within the first 1024 bytes is the spec.

Viewport comes second. Mobile browsers need it before they begin layout.

Title and description come early. They are short, they are the most important text, and they are read by social-share crawlers that may quit fetching after a few KB.

Preconnect and preload come before the styles or scripts they help. A preconnect to your CDN that comes after the <link rel="stylesheet"> to that CDN is too late — the browser has already started the connection.

Stylesheets and scripts come after the high-priority hints. They are bigger and slower; let the small important stuff land first.

ordered-head.html
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">

<title>...</title>
<meta name="description" content="...">

<link rel="preconnect" href="https://cdn.example.com">

<link rel="stylesheet" href="https://cdn.example.com/styles.css">
<script defer src="https://cdn.example.com/app.js"></script>

<link rel="icon" href="/favicon.svg">
<meta property="og:title" content="...">
</head>

The high-impact tags are at the top; the lower-priority metadata trails. The render-blocking tags (CSS, scripts) come after the hints that prepare for them.

The minimum viable head

What is the smallest head that does not embarrass you? Five lines.

minimum.html
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Page title here</title>
<meta name="description" content="One sentence about what this page is.">
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
</head>

Charset and viewport keep mobile browsers from doing stupid things. Title is the tab. Description is the search-result blurb. The icon is the favicon. Anything beyond this is opt-in based on what your page needs.

A page that ships with this head will look fine in the tab, render correctly on mobile, and present a non-broken description in search results. Add Open Graph (lesson 3) when you want social shares to look good. Add resource hints (lesson 5) when you have specific assets to optimize. Add structured data (lesson 8) when you want rich results.

Watch out

A common mistake: forgetting the viewport meta. Without it, mobile browsers render at a 980px-wide virtual viewport and zoom out to fit the screen. Your beautiful responsive layout collapses into a postage stamp. The line is two-syllable; do not skip it.

check your understanding
Your single-page app's HTML loads a 30 KB CSS file via <link rel="stylesheet">. The file lives on a CDN. You also have a <link rel="preconnect"> for that CDN. To get the most benefit from the preconnect, where should it sit?
check your understanding
You omit the <meta name="viewport"> tag. A user opens your responsive site on a phone. What do they see?
check your understanding
You have an analytics script (50 KB) that does not need to run before the page renders. Which markup is the right pattern?
next lesson →
KeepLearningcertificate
for completing
HTML document and meta
0 of 8 read