Speed is a feature. Visitors leave slow sites, especially on phones, and search engines include page experience in their rankings through Core Web Vitals: how quickly the main content appears (LCP, Largest Contentful Paint), how quickly the page responds to taps and clicks (INP, Interaction to Next Paint) and how much the layout jumps around while loading (CLS, Cumulative Layout Shift).
Many of the biggest improvements need only HTML attributes. Telling the browser an image's size stops text jumping when it loads. Marking images below the fold as lazy stops them competing with what's on screen. Preloading the hero image or a key font makes the first view appear sooner. Preconnecting to another server saves time before its files are requested.
In this lesson you'll learn these techniques, when each helps and when it backfires, and how to measure the difference with browser tools such as Lighthouse and PageSpeed Insights.
Images and iframes
<img src="hero.jpg" alt="..." width="1200" height="600" fetchpriority="high">
<img src="gallery-5.jpg" alt="..." width="400" height="300" loading="lazy" decoding="async">
<iframe src="..." title="..." loading="lazy"></iframe>widthandheightlet the browser reserve space before the image arrives, preventing layout shift. CSS can still resize it withmax-width: 100%; height: auto;.loading="lazy"delays images and iframes until they're near the screen. Never lazy-load the main image at the top of the page.fetchpriority="high"tells the browser that an image, usually the hero or LCP image, is the most important download.- Use modern formats such as WebP and AVIF with
<picture>, and responsivesrcset, covered in the responsive images lesson.
Resource hints
| Hint | Does | Use for |
|---|---|---|
<link rel="preload" href="..." as="..."> | Downloads a file early, at high priority | The hero image, a key font, critical CSS |
<link rel="preconnect" href="https://..."> | Opens the connection to a server early | Font, image or API servers you'll use soon |
<link rel="dns-prefetch" href="..."> | Looks up a server's address early | Lighter version of preconnect |
<link rel="prefetch" href="..."> | Downloads a file at low priority for the next page | The page a user will probably visit next |
Preload only one or two truly critical files. Preloading everything means nothing is prioritised, and it slows the page down.
Scripts, styles and measuring
- Load scripts with
deferorasyncso they don't block the page, as in the scripts lesson. - Keep CSS in a few files in the
<head>; CSS is needed before the page can be shown, so smaller is faster. - Every font file, third-party widget and tracking script adds weight. Ask whether each one earns its place.
- Measure: run Lighthouse in Chrome DevTools, check PageSpeed Insights for real-user data, and watch the Network panel to see what loads and when.
HTML Performance Syntax
Performance attributes
<link rel="preconnect" href="https://fonts.example.com" crossorigin>
<link rel="preload" href="/img/hero.webp" as="image" fetchpriority="high">
<link rel="preload" href="/fonts/main.woff2" as="font" type="font/woff2" crossorigin>
<img src="/img/hero.webp" alt="..." width="1200" height="630" fetchpriority="high">
<img src="/img/photo.webp" alt="..." width="600" height="400" loading="lazy" decoding="async">
<iframe src="..." title="..." loading="lazy"></iframe>
<script src="/js/app.js" defer></script>HTML Performance Summary
- Core Web Vitals measure loading (LCP), responsiveness (INP) and visual stability (CLS).
- Always set image
widthandheightto prevent layout shift. - Lazy-load images and iframes below the fold, never the hero image.
- Use
fetchpriority="high"andpreloadsparingly for the most important files. - Preconnect to servers you'll need soon, defer scripts, and measure with Lighthouse.
HTML Performance Examples
Each example runs in the page. Edit the code and press Run to see what changes.
Reserving space to stop layout shift
<style>
img { max-width: 100%; height: auto; display: block; background: #e5e7eb; }
</style>
<h3>Without size attributes the text below would jump when the photo loads.</h3>
<img src="https://picsum.photos/seed/speed/600/300" alt="Mountains under a clear sky" width="600" height="300">
<p>This paragraph stays put, because the browser reserved a 2:1 space for the image before it arrived.</p>Line-by-line explanation
- Line 2Images shrink to fit small screens while keeping their shape.
- Line 5
widthandheightgive the browser the image's proportions in advance. - Line 6The text below doesn't move when the image finishes loading.
Lazy loading a long gallery
<style>.gallery img { width: 100%; max-width: 300px; height: auto; margin: 6px 0; display: block; }</style>
<div class="gallery">
<img src="https://picsum.photos/seed/g1/300/200" alt="Gallery photo 1" width="300" height="200" fetchpriority="high">
<img src="https://picsum.photos/seed/g2/300/200" alt="Gallery photo 2" width="300" height="200" loading="lazy">
<img src="https://picsum.photos/seed/g3/300/200" alt="Gallery photo 3" width="300" height="200" loading="lazy">
<img src="https://picsum.photos/seed/g4/300/200" alt="Gallery photo 4" width="300" height="200" loading="lazy">
<img src="https://picsum.photos/seed/g5/300/200" alt="Gallery photo 5" width="300" height="200" loading="lazy">
</div>Line-by-line explanation
- Line 3The first, visible image loads immediately with high priority.
- Lines 4 to 7Later images load only as the visitor scrolls towards them, saving data on mobile.
A fast head section
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Coffee Beans | Codevra Roasters</title>
<link rel="preconnect" href="https://images.example-cdn.com">
<link rel="preload" href="https://images.example-cdn.com/hero.webp" as="image" fetchpriority="high">
<link rel="stylesheet" href="/css/site.css">
<script src="/js/app.js" defer></script>
<script src="https://analytics.example.com/a.js" async></script>
</head>Line-by-line explanation
- Line 5The connection to the image server starts straight away.
- Line 6The hero image, the largest thing on screen, downloads early.
- Line 7A single style sheet in the head.
- Lines 8 to 9Scripts don't block the page: deferred for the app, async for analytics.
Common HTML Performance Mistakes
Lazy-loading the hero image
<img src="hero.jpg" alt="Our bakery" loading="lazy"><img src="hero.jpg" alt="Our bakery" width="1200" height="600" fetchpriority="high">Lazy-loading the first image delays the most important content on the page.
Images without dimensions
<img src="product.jpg" alt="Desk lamp"><img src="product.jpg" alt="Desk lamp" width="800" height="800">Without dimensions, the page jumps when the image loads, hurting CLS.
Preloading everything
<link rel="preload" href="a.jpg" as="image">
<link rel="preload" href="b.jpg" as="image">
<link rel="preload" href="c.jpg" as="image">
<link rel="preload" href="d.jpg" as="image"><link rel="preload" href="hero.jpg" as="image">When everything is a priority, nothing is.
HTML Performance in Real Projects
Speed in practice
News sites, shops and travel sites watch Core Web Vitals in Google Search Console, because slow pages lose both rankings and sales. Image CDNs serve WebP and AVIF automatically, frameworks add fetchpriority and lazy loading by default, and teams run Lighthouse in their release checks so a heavy new image or script is caught before it reaches visitors.
HTML Performance Exercises
Answer each one and check it instantly. If you get stuck, open the hint before the answer.
Delay loading an image that's far down the page.
<img src="footer-map.png" alt="Map" width="600" height="300" loading="">
What do width and height attributes on an image prevent?
Which image should get fetchpriority="high"?
What does rel="preconnect" do?
Fix the images: the hero (first) image must not be lazy and should have high priority, and the second image needs width and height (400 by 300) and lazy loading.
<img class="hero" src="https://picsum.photos/seed/h/800/400" alt="Hero" width="800" height="400" loading="lazy">
<img class="second" src="https://picsum.photos/seed/s/400/300" alt="Second">- Hero is not lazy and has high priority
- Second image has dimensions
- Second image is lazy
HTML Performance Quiz
5 questions to check what you learned.
What does CLS measure?
- Load time
- Server speed
- Image quality
- How much the layout jumps around while loading
What does LCP measure?
- The number of links
- How long the largest visible element takes to appear
- Code length
- Colour contrast
Which tool can audit a page's performance in Chrome?
- View source
- The address bar
- Lighthouse in DevTools
- Print preview
Why is preloading many files a bad idea?
- It removes the priority benefit and competes with critical downloads
- Preload is deprecated
- Browsers ignore more than one
- It breaks images
What does decoding="async" on an image suggest?
- Download later
- Lower quality
- The browser may decode the image off the main thread so it doesn't hold up other work
- Convert the format
HTML Performance Challenge
A fast product section
Create:
- A hero
<img>with width, height andfetchpriority="high" - Two more images with width, height and
loading="lazy" - A
<link rel="preconnect">tohttps://picsum.photos
- Preconnect to picsum
- Hero image has high priority and dimensions
- Two lazy images with dimensions