learn-html-with-phoebe / Deep dive 6.3 of 3
Learn HTML with Phoebe · Deep dive 6.3 of 3

The invisible 10 lines that make your page shareable

Your page went live in Session 6. Now the head - the invisible half of the skeleton - decides everything that happens to it out in the world: what the LinkedIn card looks like when you share it, what Google prints under your name, which tiny icon sits in the tab, and how fast it loads on hotel wifi. Ten lines, outsized returns.

🔴 Self-paced ~35 min
SEO essentials Open Graph cards favicons performance hints
Part 0

Why this deep dive exists

Session 1 taught the split: head is the label on the box, body is what is in the box. This dive is about who reads the label. Search engines read it to rank you, LinkedIn and Slack read it to draw your share card, browsers read it to pick a tab icon and plan image loading. None of it renders on the page - which is exactly why these are the lines most beginners never learn, and why knowing them reads as senior.

Core - read carefully Self-study - recognition level ★ Try it now Orange panels are editable - type and watch
★ What you walk out with A copy-paste head block for your live page: honest title and description for search, a complete Open Graph set so your LinkedIn shares get the big image card instead of a bare grey link, a favicon that costs three lines, and the image-loading attributes (lazy, width+height, srcset) that make the page feel fast on any connection. Heads-up on the demos: head lines are invisible by design, so this page shows them as copy-paste blocks and saves the live panels for the image tricks, which do render.
Part 1 · covers MDN meta element + "What's in the head" going pro

SEO essentials - the search-result pitch core

How a search engine reads your page: it fetches the HTML, walks the heading outline you built in Session 1, uses the semantic elements from Session 3 to tell content from chrome, and then prints two head lines as your search result - the title as the blue link, the meta description as the text under it. Good markup was never just tidiness; it was always also how machines understand you.

LiveTitle and meta description - your search listing, written by you4 min▶

The <title> does triple duty: browser tab, bookmark name, and the clickable line in search results. The pattern that works for a personal page: Name - what you do. The meta description is the ~155 character pitch printed beneath it - not a ranking factor so much as the ad copy that decides whether a human clicks you or the result below you.

The title and meta description become your search result THE MARKUP THE SEARCH RESULT <title>Phoebe Fu - data and AI leader</title> <meta name="description" content="Data and AI leadership, hands-on builds, honest notes."> Phoebe Fu - data and AI leader https://you.github.io Data and AI leadership, hands-on builds, honest notes on making analytics ship. title is the blue headline; meta description is the grey pitch printed underneath it.
🔍 Click to zoom - two invisible head lines write your search-result ad copy
Copy-paste, then personalize<title>Phoebe Fu - data and AI leader</title>
<meta name="description" content="Data and AI leadership, hands-on builds, and honest notes on making analytics teams ship. Based in Sydney.">

These render nothing, so no playground here - the honest test is searching your own name once your page has been live a few weeks. Two rules: every page gets a unique title, and the description is written for humans (search engines happily skip keyword soup and generate their own instead).

Real world

Search for any well-known person in data and read the result snippets. The crisp ones ("X - AI researcher at Y. Writing about Z.") are hand-written meta descriptions; the ragged ones with "..." mid-sentence are search engines improvising from page text because nobody wrote the line. Thirty seconds of writing beats the robot's guess.

Self-studycanonical and robots - two lines of honesty2 min read▶
  • <link rel="canonical" href="https://you.github.io/"> - declares the one true URL when the same page is reachable several ways (with and without a trailing slash, with tracking parameters). Search engines then pool all the credit onto one address instead of splitting it.
  • <meta name="robots" content="noindex"> - asks search engines not to list the page. For drafts and private client pages, not for your portfolio. Honesty note: it is a request, not a lock - real secrets need real access control, never just a meta tag.

That is the whole beginner SEO story, and it is deliberately boring: no tricks, no meta keywords (dead since 2009), just accurate labels on well-structured content. The heading discipline from Session 1 is doing more for your ranking than any tag in this section.

Part 2 · covers the Open Graph protocol (ogp.me) · the star section

Open Graph - the share card that sells your link core

Paste a link into LinkedIn and a card appears: big image, bold title, grey description. That card is not designed by LinkedIn - it is read from the shared page's head, from og: meta tags (the Open Graph protocol, born at Facebook, now the standard everywhere: LinkedIn, Slack, WhatsApp, iMessage, Discord). No og tags means a bare grey link nobody clicks. For anyone sharing their work on LinkedIn, these six lines are the highest-leverage HTML on the entire page.

og:image lives here 1200 x 630, the whole card og:image 1200x630 PNG or JPG, absolute URL og:title bold line, ~60 chars before cut og:description grey pitch, often trimmed ~110 og:url shown as the bare domain Every platform draws the same four ingredients its own way. You write them once, in the head.
🔍 Click to zoom - a LinkedIn share card dissected: each visible part maps to one og: meta tag in your head.
LiveThe complete OG block - copy, paste, personalize5 min▶

Six og tags plus one Twitter/X line cover every platform that matters. Head-only, invisible on the page itself, so this is a copy-paste block rather than a live panel - the "preview" happens on LinkedIn:

The full set for your page<meta property="og:type" content="website">
<meta property="og:title" content="Phoebe Fu - data and AI leader">
<meta property="og:description" content="Builds, essays, and honest notes on data and AI leadership.">
<meta property="og:image" content="https://you.github.io/card.png">
<meta property="og:url" content="https://you.github.io/">
<meta name="twitter:card" content="summary_large_image">
  • og:image is the card. Make a 1200 x 630 PNG or JPG (the universal safe size): your name big, one line of what you do, brand color background. Any slide tool exports one in five minutes. The URL must be absolute - crawlers do not resolve relative paths from your head.
  • og:title can differ from your title tag. The title tag serves search; og:title serves the feed. "Phoebe Fu - data and AI leader" works for both, but you are allowed a punchier feed version.
  • twitter:card summary_large_image is the one non-og line worth adding: it asks X (and several tools that reuse the tag) for the big-image layout instead of a thumbnail.
Self-studyDebugging a share card - the crawler cache gotcha3 min read▶

The mechanic to understand: when you paste a link, the platform's crawler fetches your page right then, reads the og tags, and caches the result - often for days. Two consequences:

  • Test before you post. Paste your URL into opengraph.xyz to preview the card across platforms, or use LinkedIn's own Post Inspector (search "LinkedIn Post Inspector", it needs a login). Both show exactly what the crawler sees.
  • Fixed a typo but the old card keeps appearing? That is the cache. The Post Inspector re-scrapes on demand; failing that, sharing the URL with a harmless query string like ?v=2 forces a fresh fetch.
Real world

Watch your LinkedIn feed for a day: posts whose links show big branded cards get read, bare grey links scroll past. Same content, different head. People who share their work weekly get more return from these six lines than from any other HTML they will ever write.

The whole workflow, start to finish:

Make the 1200 x 630 image: name big, one line of what you do, brand background. Export as PNG, name it card.png, put it next to your index.html.

Paste the six-line block into your head, swap in your real texts and your page's absolute URLs.

Push, wait for GitHub Pages to update, then paste your URL into opengraph.xyz. Fix anything that looks off.

Share on LinkedIn. Big card appears. Take the small victory lap - you earned it in the head.

Part 3 · covers favicon links (MDN "What's in the head" extras)

Favicons in 2026 - the three-line set core

The favicon is the tiny icon in the tab, the bookmark list, and the phone home screen. The internet is full of 20-line favicon incantations from 2015; the honest modern set is three lines: an SVG that scales everywhere, a PNG for Apple home screens, and a classic .ico for old clients and stray crawlers.

LiveThe minimal honest set3 min▶
Three lines, done<link rel="icon" href="/favicon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/apple-touch-icon.png" sizes="180x180">
<link rel="icon" href="/favicon.ico" sizes="32x32">
  • The SVG is the star - one vector file, sharp at every size, and you can write it by hand with your Deep dive 6.2 skills. Modern browsers pick it first.
  • apple-touch-icon is the 180 x 180 PNG iOS uses when someone saves your page to their home screen. The sizes attribute tells the browser which dimensions a link offers so it can choose without downloading.
  • favicon.ico is the 1999 veteran. Browsers still request /favicon.ico by convention even with no link tag (check any server log), so parking one there silences 404s.

And the beginner-favorite trick - an emoji as your favicon, via a handwritten SVG, no image editor involved:

Save as favicon.svg<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
  <text y="0.9em" font-size="90">📊</text>
</svg>

Head links do not render in a page body, so no live panel - drop the file next to your index.html, add the link line, hard-refresh, and watch your tab. That five-second icon change is the most visible payoff in this whole dive.

Self-studyThe rest of the head drawer, on sight2 min read▶

Three more head lines you will meet in every view-source, now demystified:

  • <meta name="viewport" content="width=device-width, initial-scale=1.0"> - the line that makes pages readable on phones instead of rendering a shrunken desktop. It has been in your skeleton since Session 1; now you know its job.
  • <meta name="theme-color" content="#E34F26"> - tints the browser chrome around your page on mobile. Pure polish, one line.
  • <meta charset="UTF-8"> - the Session 1 veteran, mentioned once more for placement: keep it first in the head, before any text a broken encoding could scramble.
Part 4 · covers MDN lazy loading + responsive images (srcset, sizes, picture)

Performance hints - attributes that buy speed core

The browser starts planning the page the instant HTML arrives - before images download, before CSS settles. These attributes are you leaving notes for that planner: what size things will be, what can wait, what matters most. No build tools, no JavaScript: pure HTML attributes, mostly on the <img> tag you have used since Session 3.

Livewidth + height - the anti-jump insurance3 min▶

Give every image its width and height attributes. The browser uses their ratio to reserve the right box before the image arrives, so the text below does not jump when it lands. That jump has a name - layout shift - and it is the thing that makes you tap the wrong button on slow news sites. CSS still controls the displayed size; the attributes just promise the shape.

✗ no width or height <img src="...400x260.jpg" alt="landscape"> Text below jumps when it loads. That jump is called layout shift. ✓ width and height set <img src="...400x260.jpg" width="400" height="260"> Space is reserved before it loads. Text below never moves. CSS still controls the displayed size - these attributes just promise the shape up front.
🔍 Click to zoom - two attributes are the entire fix for images that make the page jump
<img src="https://picsum.photos/seed/phoebe/400/260"
     width="400" height="260"
     alt="A calm placeholder landscape">
<p>This paragraph never jumps: the box
above was reserved from the ratio
before the image finished loading.</p>
Liveloading="lazy" - do not load what nobody scrolled to3 min▶

By default the browser fetches every image on the page immediately, including the ones three screens down. loading="lazy" defers an image (or iframe) until the reader scrolls near it. One rule saves you from the classic mistake: never lazy-load what is visible on arrival - lazy-loading your hero image makes the most important pixels arrive last.

<p>Above the fold: loads eagerly.</p>
<img src="https://picsum.photos/seed/one/380/220"
     width="380" height="220" alt="First, eager">
<p>Below the fold: these can wait.</p>
<img src="https://picsum.photos/seed/two/380/220"
     width="380" height="220" loading="lazy"
     alt="Second, lazy">
<img src="https://picsum.photos/seed/three/380/220"
     width="380" height="220" loading="lazy"
     alt="Third, lazy">

Sibling hint, recognition level: fetchpriority="high" on the one image that IS your page (the hero) tells the browser to fight for it first. New-ish but harmless where unsupported - unknown attributes are simply ignored, HTML's oldest safety feature.

Livesrcset + sizes - one image, several weights4 min▶

A phone on 4G should not download the 1600-pixel version of your headshot. srcset lists the same image at several widths (the 400w style numbers are each file's real pixel width), and sizes tells the browser how wide the slot will be, so it can pick the lightest file that still looks sharp. You provide the menu; the browser orders.

<img src="https://picsum.photos/seed/hero/400/250"
     srcset="https://picsum.photos/seed/hero/400/250 400w,
             https://picsum.photos/seed/hero/800/500 800w,
             https://picsum.photos/seed/hero/1200/750 1200w"
     sizes="(max-width: 600px) 90vw, 600px"
     width="400" height="250"
     alt="One image, three candidate files">
Self-studypicture - art direction, not just resizing3 min read▶

srcset serves the same picture at different weights. <picture> goes further: genuinely different images for different situations - a wide landscape crop on desktop, a tight square crop on phones. The browser walks the <source> children top to bottom, takes the first whose media condition matches, and falls back to the inner <img> (which also carries the alt text - always).

<picture>
  <source media="(min-width: 500px)"
          srcset="https://picsum.photos/seed/wide/600/220">
  <img src="https://picsum.photos/seed/tall/260/260"
       width="260" height="260"
       alt="Square crop for narrow screens">
</picture>
<p>Same subject, different crop per screen -
that is art direction.</p>

Bonus use, no media queries: a <source type="image/avif"> then type="image/webp" then a JPG fallback img serves modern formats to modern browsers and never breaks old ones.

Homework

Try it yourself - this week ◐ 30-40 min total

Source material

Official sources covered

This dive teaches the working content of the MDN meta element docs, the Open Graph protocol, and MDN's lazy loading and responsive images guides. Full spec depth stays with the originals - this page is the working subset.

✓MDN: meta element + head essentials for SEOPart 1 - title patterns, description, canonical, robots honesty
✓Open Graph protocol (ogp.me) + twitter:cardPart 2 - the six-line block, 1200x630 recipe, cache debugging
✓Favicon link relationsPart 3 - svg + apple-touch-icon + ico, sizes attribute, emoji trick
✓MDN: Lazy loadingPart 4 - loading="lazy" on images and iframes, never on the hero
✓MDN: Responsive images (srcset, sizes, picture)Part 4 - weight menu vs art direction, format fallbacks
◐fetchpriorityrecognition level - hero images first; safe where unsupported
Check yourself

Three questions before you go 🎯 ◐ 90 seconds

1 · You share your page on LinkedIn and get a bare grey link, no image card. The first thing to check is...

The crawler reads the head, not your settings and not the body. No og:image (or a relative URL it cannot fetch) means no card - and remember the cache: after fixing, force a re-scrape with the Post Inspector.

2 · Your hero image sits at the very top of the page. Which attribute set is right for it?

Lazy is for below the fold; lazy-loading the first thing visitors see delays your most important pixels. Width and height reserve its box so nothing jumps, and fetchpriority tells the browser to fight for it first.

3 · In srcset="photo-400.jpg 400w, photo-800.jpg 800w", what does 400w describe?

Each w number states the file's actual width in pixels - facts about the menu. The browser combines them with your sizes hint and the device to choose; you never dictate the choice directly.

Deep dive 6.3 cheat sheet · pin this

Title pattern"Name - what you do". Unique per page. Serves the tab, bookmarks, and the blue line in search results.
Meta description~155 chars, written for humans - the pitch under your search result. Skip it and the robot improvises.
OG blockog:type, og:title, og:description, og:image, og:url + twitter:card summary_large_image. Six lines, every platform.
og:image recipe1200 x 630 PNG/JPG, absolute URL. Debug with opengraph.xyz or LinkedIn Post Inspector; crawlers cache for days.
Favicon setfavicon.svg (star) + apple-touch-icon 180x180 + favicon.ico at the root. Emoji-in-SVG = icon with zero image tools.
width + heightOn every img. The ratio reserves the box before pixels arrive - no layout jump. CSS still sets displayed size.
loading="lazy"Below-fold images and iframes only. Never the hero - that one gets fetchpriority="high" instead.
srcset vs picturesrcset = same image, several weights, browser picks. picture = different crops or formats per condition, you direct.