The HTML document and its head
That skeleton Emmet gave you has about eight lines in it, and most people copy it for years without knowing what four of them do. Two of those four are the difference between a site that works on a phone and one that does not.
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
</html>
<!doctype html>
Not an element, and not optional. It tells the browser to use standards mode.
Leave it out and the browser uses quirks mode, which emulates bugs from Internet Explorer 5 in order not to break sites from 1999. The most visible effect: the box model changes, so every width you set is computed differently and your layout is subtly wrong everywhere with nothing to point at.
It has no attributes and no closing tag. Type it once, at the very top, and never think about it again.
<html lang="en">
The lang attribute is the one people delete without knowing what it does, and it
does four things:
- Screen readers choose a voice and pronunciation from it. English text read by a Hindi voice is not slightly wrong; it is unintelligible. This is the single cheapest accessibility win available to you — one attribute.
- Browsers offer to translate based on it.
- Hyphenation and quote marks follow it.
- Search engines use it.
Use en for English, or en-IN if you want Indian English spelling and date
conventions in the browser's own features. If a section of the page is in another
language, say so on that element:
<p>The shop is called <span lang="hi">किराना</span>.</p>
<head> versus <body>
Everything in <head> is about the page: its title, its character encoding,
its stylesheets, how it should appear when shared. None of it is displayed.
Everything in <body> is the page.
The commonest beginner mistake is putting content in the head. It does not
render, and nothing tells you why — the browser quietly moves it or ignores it.
If content is mysteriously invisible, check which side of </head> it is on.
<meta charset="UTF-8">
The character encoding. It must be UTF-8, and it must be in the first 1024 bytes of the document, which is why it goes first inside the head.
Without it, the browser guesses. Guessing works for plain English and fails the moment you write anything else:
₹450 becomes ₹450
Bengaluru — Pune Bengaluru â€" Pune
किराना किराना
Those are called mojibake, and if you have ever seen ’ where an apostrophe
should be, this was why. The rupee sign is the one that will catch you first.
<meta name="viewport" …>
The most important line in the file for mobile, and the one whose absence causes the classic "my responsive site is not responsive" problem.
<meta name="viewport" content="width=device-width, initial-scale=1.0">
Here is the history, because it explains an otherwise baffling default. When the iPhone arrived, every site was built for a 1000-pixel-wide desktop window. Showing those sites 320 pixels wide would have broken all of them. So mobile browsers lie: they claim to be about 980 pixels wide and then shrink the whole page to fit, which is why an old site on a phone looks like a tiny, readable-if-you-zoom version of the desktop layout.
width=device-width switches the lie off: use the real width. initial-scale=1.0
says do not zoom to start with.
Without this line, all your media queries in module 4 are measured against a pretend 980-pixel viewport, never match, and your mobile layout never appears. The page is not broken and there is no error — the phone is just showing you a shrunken desktop. It is one of the most common real bugs in this field and it is one line.
You can prove it in two lines of JavaScript. On a 375-pixel-wide phone viewport, with the meta tag missing:
window.innerWidth 980
matchMedia("(max-width: 600px)").matches false
And with it present:
window.innerWidth 375
matchMedia("(max-width: 600px)").matches true
That false is your entire mobile stylesheet not applying.
What not to add: user-scalable=no or maximum-scale=1.0. They stop a person
pinch-zooming, which for anybody with limited vision makes your site unusable.
It is a WCAG failure and there is no good reason for it.
<title>
Shown in the browser tab, in bookmarks, in search results, and read out first by a screen reader. It is also what somebody sees in their history three weeks later.
<title>Document</title> <!-- shipped by accident, often -->
<title>Home</title> <!-- which site? -->
<title>Sharma Kirana — Fresh groceries in Kothrud</title>
Put the specific part first. A tab strip shows about twenty characters, so
Sharma Kirana — About beats About — Sharma Kirana when six tabs are open.
The rest of a real head
Beyond the skeleton, four things a finished page has:
<meta name="description" content="Daily groceries and home delivery in Kothrud, Pune. Open 7am to 10pm.">
<link rel="stylesheet" href="styles.css">
<link rel="icon" href="favicon.ico">
<link rel="canonical" href="https://sharmakirana.com/">
description is not used for ranking, but it is often the text under your
link in search results. 150-ish characters, written for a person.
stylesheet goes here, in the head, because of the render-blocking behaviour
from lesson one — the browser needs it before it paints. Put it at the bottom of
the body instead and you get a flash of unstyled content.
icon is the little tab image. Its absence generates a 404 on every page load,
which you will notice in the Network tab.
canonical says "this is the real address of this page", which matters once
the same content is reachable at more than one URL.
And for social sharing, Open Graph tags — what WhatsApp uses to build a preview card:
<meta property="og:title" content="Sharma Kirana — Fresh groceries in Kothrud">
<meta property="og:description" content="Daily groceries and home delivery in Kothrud, Pune.">
<meta property="og:image" content="https://sharmakirana.com/preview.jpg">
Without og:image, a link shared on WhatsApp is a bare grey box. With it, it is a
card with a picture. For a small business site that is a real difference in
whether anybody taps it.
Order inside the head
It matters more than you would guess:
<meta charset>— first, so the browser decodes everything after it correctly.<meta name="viewport"><title>- Everything else.
Check your work
What <!doctype html> prevents. Quirks mode, which changes the box model and
breaks widths.
Four things lang does. Screen reader voice, translation offers, hyphenation,
search engines. The voice is the important one.
What goes in the head. Everything about the page. Nothing that displays — and content placed there silently does not render.
Why UTF-8, first. Otherwise the browser guesses and ₹450 becomes ₹450.
It must be within the first 1024 bytes.
What the viewport meta tag does. Switches off the 980-pixel lie so media queries measure the real width. Without it your mobile layout never appears and there is no error.
What never to put in it. user-scalable=no — it blocks pinch-zoom and fails
WCAG.
Why the specific part of a title goes first. A tab shows about twenty characters.
Why the stylesheet is in the head. It is render-blocking; lower down gives a flash of unstyled content.
What a missing favicon costs. A 404 on every page load.
What og:image changes. Whether a WhatsApp share is a card or a grey box.
Practice
- Delete
<!doctype html>from a page with a width set on a box. Compare the rendered width. - Remove
lang, then setlang="hi"on an English page. If you can, listen to it with a screen reader. - Move an
<h1>inside<head>and reload. Describe what happens. - Delete the
charsetline and put₹450,—andकिरानाon the page. Reload. - Put the charset line back but at the end of the head, after 1024 bytes of comments. See whether it still works.
- Remove the viewport meta tag, open the page in devtools device mode as an
iPhone, and run
window.innerWidthandmatchMedia("(max-width: 600px)").matchesin the console. Add the tag back and run them again. You should see 980/false, then 375/true. - Add
user-scalable=no, then try to pinch-zoom on a real phone. Then remove it. - Write a real
<title>for a kirana shop page, under 60 characters, specific part first. - Add a
descriptionand a favicon. Confirm in the Network tab that the favicon 404 is gone. - Add Open Graph tags with an image and send the deployed link to yourself on WhatsApp. Compare before and after.
Official documentation
- MDN — The meta element — Every
nameandpropertyvalue, including the ones this lesson skipped. - MDN — Viewport meta element — The full behaviour of
width=device-widthand why the 980px default exists. - The Open Graph protocol — The specification for the tags WhatsApp and every social app read.
Next: the elements that hold your actual words, and why the choice matters.
Stuck on this lesson?
Being stuck is part of it — but being stuck alone for three days is not. Our internship programme pairs this curriculum with code review and one-to-one help from working developers, and it is free.
About the internship