HTML Performance: Making Pages Load Fast
A page can be beautiful, accurate, and well built, and still lose its visitors in the first few seconds. People do not wait. On a slow phone in a moving train, every extra second is a chance for someone to give up, and every kilobyte costs real money for someone on a limited data plan.
Performance is how quickly and how smoothly your page loads and responds. A surprising amount of it is decided by plain HTML: which files you ask for, in what order, with which attributes. This section teaches you those choices, one at a time, and how to measure whether they worked.
What You Will Learn in This Sectionβ
- How a browser loads and shows a page
- What blocks the page, and what does not
- How to use resource hints: preload, prefetch, preconnect, and dns-prefetch
- How to load scripts without freezing the page:
deferandasync - How to load images at the right size and at the right time
- What the Core Web Vitals measure
- How to measure and keep your gains
The Big Ideaβ
- HTML Code
- Loading Timeline Lab
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>The Bread Bin</title>
<!-- Open the connection to a server you will need soon -->
<link rel="preconnect" href="https://fonts.example.com" crossorigin>
<!-- Fetch the main image early, because CSS would reveal it late -->
<link rel="preload" as="image" href="/img/hero-1200.webp">
<link rel="stylesheet" href="/styles.css">
<!-- Download now, run after the page is ready -->
<script src="/app.js" defer></script>
</head>
<body>
<img src="/img/hero-1200.webp" alt="A golden loaf on a wooden board" width="1200" height="600">
<!-- Far below the first screen: wait until it is needed -->
<img src="/img/gallery-1.webp" alt="Rye loaves on a rack" width="600" height="400" loading="lazy">
</body>
- HTML document: 0 to 300 ms
- styles.css (in the head): 220 to 520 ms
- app.js (blocking): 230 to 630 ms
- app.js runs: 630 to 780 ms
- Hero image: 520 to 1220 ms
- Third-party tag (connects first): 1180 to 1480 ms
- First content shown (FCP): 780 ms
- Hero image shown (LCP): 1220 ms
- app.js ready: 780 ms
- Third-party tag loaded: 1480 ms
This is a simplified simulation with made-up numbers, so you can see the relative effect of each choice. Real browsers are smarter and messier: they share bandwidth between files, scan ahead for resources, cache files, and give different files different priorities. Never trust a simulation for your own site. Measure it, with the tools described below.
Try the options one at a time. Watch what a blocking script does to the first paint, and what a preload does to a late-found image.
Why Performance Mattersβ
- People leave slow pages. Studies by large sites have repeatedly linked faster pages to more completed visits and purchases. The exact numbers vary, so measure your own site.
- Not everyone has a fast phone or network. A page that is fine on your laptop may be painful on a mid-range phone on a weak signal.
- Data costs money. Heavy pages are expensive for people on limited plans.
- Speed is part of accessibility. Long freezes and jumping layouts are hardest on people who use assistive technology, have motor or cognitive difficulties, or need more time.
- Search engines notice. Page experience is one of many signals, and a small one next to content quality. See HTML SEO Basics.
- It saves energy. Less data and less work means less power used, on both the server and the device.
How a Browser Loads a Pageβ
In very simple terms:
- Request. The browser asks the server for the HTML, and waits for the first byte (the time to first byte).
- Parse. It reads the HTML from top to bottom, and discovers other files to fetch: stylesheets, scripts, images, fonts.
- Fetch. It downloads those files, often several at once, on connections it may need to open first (a DNS lookup, a TCP connection, and encryption).
- Build. It combines the HTML and the CSS, works out the layout, and paints the page.
- Run. It runs JavaScript, which can change the page, and respond to the visitor.
At each step, something can wait on something else. Performance work is mostly about removing the waiting.
What blocks the pageβ
| Thing | What it blocks | Typical fix |
|---|---|---|
| A stylesheet in the head | Painting the page (the browser will not draw without the styles) | Keep CSS small, and load only what is needed first |
| A plain script | Reading the rest of the HTML while it downloads and runs | Use defer or async |
| A late-found important file | The picture or font arriving when it is needed | preload, or put it in the HTML |
| A new connection to another server | The first request to it | preconnect |
| A large, unneeded file | Bandwidth for everything else | Smaller files, lazy loading, responsive images |
What We Measureβ
Three numbers, called the Core Web Vitals, describe the experience people have:
| Metric | What it measures | Good means |
|---|---|---|
| LCP | How soon the biggest visible thing appears | Up to 2.5 seconds |
| INP | How quickly the page responds when you use it | Up to 200 milliseconds |
| CLS | How much the layout jumps while loading | Up to 0.1 |
These are the thresholds Google published at the time of writing, and they may change. Check your own pages, and test your understanding:
- LCP (Largest Contentful Paint): how long until the biggest thing in view has appeared. Loading speed.
- INP (Interaction to Next Paint): how quickly the page responds after a tap, click, or key press. Responsiveness.
- CLS (Cumulative Layout Shift): how much the page jumps around while loading. Visual stability.
Rate each result. Use the published thresholds: LCP good up to 2.5 s and poor over 4 s. INP good up to 200 ms and poor over 500 ms. CLS good up to 0.1 and poor over 0.25.
These are the thresholds Google publishes at the time of writing. The set of metrics and the numbers can change, so check the current web.dev documentation. The full lesson is Core Web Vitals, in this section.
Lab data and field dataβ
- Lab data comes from a test you run, on one device, on one connection: Lighthouse, PageSpeed Insights, WebPageTest, and the browser's developer tools. It is repeatable, and good for finding causes.
- Field data comes from real visitors on their real devices: Search Console's Core Web Vitals report, and real user monitoring. It shows what people actually experience, and is what matters most.
A good habit is to find problems with lab tests, and confirm with field data.
Which Tool for Which Job?β
The lessons in this section each add a tool. Match them to the problems they solve:
Choose the best tool for each problem.
What Is in This Sectionβ
Foundationsβ
HTML Performance Basics
What makes pages slow, and the HTML habits that make them fast.
Critical Resources
Finding the few files that must arrive first, and putting them first.
Core Web Vitals
LCP, INP, and CLS: what they measure, and how to improve them.
Resource Hintsβ
Resource Hints
How preload, prefetch, preconnect, and dns-prefetch differ.
Preload
Fetching a file you know the page needs, earlier than the browser would.
Prefetch
Quietly fetching what the next page will need.
DNS Prefetch
Looking up another site's address ahead of time.
Preconnect
Opening a connection to another origin before you need it.
Loading Scriptsβ
Script Loading
How classic, module, defer, and async scripts affect the page.
defer
Download early, run after the page is parsed, in order.
async
Download early, run as soon as ready, in any order.
Imagesβ
Lazy Loading
Waiting to load images and frames until they are needed.
Responsive Images and Performance
Sending each device an image of the right size.
How to Measureβ
You cannot improve what you do not measure. These tools are free, and a good place to start:
- Lighthouse, built into Chrome DevTools. It tests one page, and suggests fixes.
- PageSpeed Insights. It runs Lighthouse, and also shows field data for popular pages, where available.
- Chrome DevTools, Network panel. It shows every file, when it started, and how long it took (the waterfall).
- Chrome DevTools, Performance panel. It shows what the browser did, and when.
- WebPageTest. It tests from different places, devices, and connection speeds.
- Search Console's Core Web Vitals report. It shows real-visitor data for your whole site.
Habits that make your tests honest:
- Throttle the network and the CPU in DevTools. Your development machine is probably much faster than your visitors'.
- Test a cold load (an empty cache), and a repeat load.
- Test on a real mid-range phone when you can.
- Run each test several times, since results vary.
- Change one thing at a time, so you know what helped.
Five Habits to Start Todayβ
- Send less. Smaller images, fewer scripts, and no files you do not use.
- Put the important things first. The main image, the main styles, and the main script.
- Do not block. Use
deferorasyncfor scripts. - Reserve space. Give images and embeds a
widthandheight, so the page does not jump. - Measure. Check Lighthouse and your field data, not your feelings.
Performance Checklist for Any Pageβ
- The page works with a slow connection and a slow phone
- CSS in the head is small, and only what is needed first
- Scripts use
deferorasync, not plain blocking tags - The main image is found early, not lazy-loaded, and not too big
- Images below the first screen use
loading="lazy" - Every image and embed has a
widthandheight - Images use modern formats and responsive sizes
- Connections to other servers use
preconnectonly when they are needed - No unused scripts, styles, or fonts
- Core Web Vitals checked in the lab and in the field
Security and Privacy Notesβ
- Third-party scripts are a risk. Every analytics, chat, ad, or widget script runs with the full power of your page. A compromised or careless provider can read what visitors type, or change your page. Use only what you need, from providers you trust, and consider the
integrityattribute for files that do not change. - Hints contact other servers early.
preconnectanddns-prefetchmake the visitor's browser contact a third party before the visitor does anything, which shares their address and some details with that party. If you need consent first (for example for analytics or advertising services), do not hint those hosts until consent is given. This is not legal advice, so check the rules that apply to you. - Preload and prefetch only public resources. Do not hint at private, personal, or one-time URLs. A prefetched address is fetched whether or not the visitor ever goes there, and can trigger actions or appear in logs.
- Measuring collects data. Real user monitoring records things about your visitors' devices and pages. Collect the least you need, say what you collect, and respect consent rules.
- Caching can leak. Do not let private or personalised pages be stored by shared caches. Check your cache headers.
- A content security policy can limit which hosts can load scripts, which also stops a hint pointing at an unexpected host from helping an attacker.
Global Audience Notesβ
- Many of your readers are on slow networks and modest phones. Design for them first, and everyone else gets a bonus.
- Data is expensive in many places. Heavy pages and autoplaying media can cost people real money. Offer lighter options, and respect the
Save-Datapreference where supported. - Distance adds delay. A content delivery network (CDN) serves files from near your readers, and is one of the biggest wins for a worldwide audience.
- Scripts add weight. Fonts for Chinese, Japanese, and Korean can be very large, so use subsets, system fonts, or only the weights you need.
- Third-party services may be slow, or blocked, in some countries. A page should still load if a widget does not.
- Test from other places. WebPageTest and similar tools can run from different regions and on different connections.
- Use plain, small, well-compressed files, so the page works on older browsers and devices too.
Common Mistakes to Avoidβ
- Optimising before measuring.
- Lazy-loading the main image, which makes the page seem slower.
- Plain scripts in the head that block the page.
- Preloading everything, which then competes with the files that matter.
- Preconnecting to many hosts you barely use.
- Huge images, displayed small.
- No
widthandheight, so the layout jumps. - Too many third-party scripts.
- Testing only on a fast machine and a fast connection.
- Trusting a single score instead of looking at what the page does.
- Making a change, and never checking that it helped.
- Forgetting repeat visits, where caching changes everything.
Practice Timeβ
Try these in your browser and your editor:
- Use the loading timeline. Which single change helps the most? Which does nothing?
- Turn on "loading=lazy" for the hero image. What happens to the LCP, and why?
- Take the Core Web Vitals quiz. Which number surprised you?
- Take the tool matcher quiz. Which two tools did you confuse?
- Run Lighthouse on a page you built, and read its three biggest suggestions.
- Open DevTools, then the Network panel, and reload. Which file takes the longest?
- Throttle the network to a slow setting, and reload. What do you see first?
- Find a plain script in the head of a page you built, and add
defer. What changes? - Add
widthandheightto every image on a page, and watch for layout jumps. - Bonus: run PageSpeed Insights on a site you use daily. What does the field data say?
Quick Recapβ
Click a question to check your answer.
1. What is web performance?
How quickly and smoothly a page loads and responds. Much of it is decided by which files the HTML asks for, in what order, and with which attributes.
2. What blocks a page from appearing?
Stylesheets in the head, and plain scripts that stop the browser reading the rest of the HTML while they download and run. Late-found important files and slow connections also delay things.
3. What are the three Core Web Vitals?
LCP (how soon the biggest thing appears), INP (how quickly the page responds), and CLS (how much the layout jumps).
4. What is the difference between lab data and field data?
Lab data comes from a test you run on one device and connection. Field data comes from real visitors. Find problems with lab tests, and confirm with field data.
5. Which scripts should use defer or async?
Almost all of them. Use defer for scripts that need the page and must run in order, and async for independent scripts such as analytics.
6. Why should you test with throttling?
Your own machine and network are probably much faster than your visitors'. Throttling shows what a slower phone and connection experience.
Key Takeawaysβ
- Performance is about removing waiting: for files to be found, fetched, and run.
- HTML decides a lot: what you load, in what order, and how.
- Do not block the page. Use
deferandasync. - Help the browser find important files early, with the right element or a preload.
- Do not load what is not needed, and do not send more than the screen needs.
- Reserve space for images and embeds with
widthandheight. - Measure in the lab and in the field, and check that each change helped.
- Design for slow networks and modest phones first.
Start with HTML Performance Basics, and work through the lessons in order.
βββ 15-performance/
β βββ index.mdx
β βββ
β βββ resource-hints.mdx
β βββ preload.mdx
β βββ prefetch.mdx
β βββ dns-prefetch.mdx
β βββ preconnect.mdx
β βββ lazy-loading.mdx
β βββ script-loading.mdx
β βββ defer.mdx
β βββ async.mdx
β βββ responsive-images-performance.mdx
β βββ critical-resources.mdx
β βββ core-web-vitals.mdx