top of page
logo-2-color_2x.png

Responsive Images and Page Weight

Points: 

5

Due By:

February 24, 2026 at 8:00:00 PM

Overview

You will be learning how to optimize websites with image in the HTML. There will be a few CSS nicities to make things look better, but the majority of the work will be done by using HTML tags and attributes.


This assignmenet is build off of the responsive images and sizes lesson.





Deliverable

Completed page-weight html and css files.





Starting Files

Please download and extract the files to get started.


https://www.dropbox.com/scl/fi/ltw3f06fmt3n0l6i1utjt/responsive-image-exercise.zip?rlkey=fzzzp9o6l98zp4b03ujh86hq4&st=3q6kziix&dl=0





Exercise 1 - Page Weight


Images are almost always the #1 reason a webpage is slow. A single unoptimised hero image can weigh more than every other resource on the page combined. This lesson has two phases:

  1. Phase 1 — Design first. Get the layout looking great using CSS grid, clip-path, object-fit, and container queries.

  2. Phase 2 — Performance. Measure with Lighthouse, then apply responsive images, srcset, modern formats, and preloading to slash the page weight.


You'll start with the starter files (above that you downloaded) and incrementally improve them, running a Lighthouse audit after each change so you can see the impact in real numbers.



Notice that the HTML has no srcset, no preloading, and every image is served at full 1280 × 720 resolution regardless of screen size. Additionally, it has not specified widths or heights for the images.

Design First - Responsive Hero Shape


The hero uses a parallelogram clip-path made with percentage values. That looks fine on large screens, but at narrow widths the clipped edges chew into the text.


The fix: swap the percentage-based clip-path for a viewport-unit version. In page-weight.css, find the two clip-path lines inside .hero and switch which one is commented out:


/* Before (comment this one out) */
clip-path: polygon(25% 0%, 100% 0%, 75% 100%, 0% 100%);

/* After (uncomment this one) */
clip-path: polygon(10vw 0vh, 100vw 0vh, 90vw 100vh, 0vw 100vh);

Why does this help? Percentage values are relative to the element — as the element shrinks, so does the visible area. vw/vh values are relative to the viewport, so the absolute pixel inset stays proportional to the screen, not the element.




Design First - Fixing The Photo Cards


Right now the grid images render at their native size — no cropping, no consistent shape. The result looks chaotic. We need each card to act as a fixed-ratio window that crops its image cleanly.


In page-weight.css, scroll to the bottom and uncomment all the rules inside div.photo and div.photo img:


div.photo {
  aspect-ratio: 16/9;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}

div.photo img {
  display: block;
  width: 100%;
  object-fit: cover;
}

Key concepts


aspect-ratio: 16/9 locks the card to a widescreen shape.


overflow: hidden clips any image that bleeds outside.


object-fit: cover tells the image to fill the card entirely, cropping rather than squishing.





How to Measure Page Weight in Chrome


Google Chrome ships with a built-in auditing tool called Lighthouse. It simulates a mid-tier device on a slow 4G connection and gives you a score out of 100 for Performance, Accessibility, and more.



Running a Lighthouse Audit


1. Open your page in Chrome in an Incognito window. Right-click anywhere and choose:

Inspect or F12 (win) (mac) Cmd+Opt+I.

2. In DevTools, click theLighthousetab. If you don't see it, click the >> overflow arrow.


3 Under Categories, checkPerformance. Under Device, chooseMobile (it's the harder target).


4 Click Analyze page load. After 30–60 seconds you'll get a detailed report.





Phase 2 - Reduce Page Weight


Now that the design looks good, let's make it fast. Run Lighthouse on your current page and note the score — that's your baseline. Each exercise below will improve it.



Responsive Images With SRCSET and SIZES


Right now every grid image is served at 1280 × 720 — even on a phone where it renders at 300 × 170. That's roughly 18× more pixels than needed. The browser has no way to know which size is appropriate because we haven't told it.


srcset gives the browser a menu of image sizes. sizes tells it how wide the image will actually render. The browser picks the best match.

Update each photo card in your HTML. Here is the pattern (using photo 101 as the example):


<!-- Before -->
<img src="https://picsum.photos/id/101/1280/720" alt="Photo 1">

<!-- After -->
<img
  src="https://picsum.photos/id/101/640/360"
  srcset="
    https://picsum.photos/id/101/400/225   400w,
    https://picsum.photos/id/101/640/360   640w,
    https://picsum.photos/id/101/1280/720 1280w
  "
  sizes="(max-width: 40em) 100vw,
         (max-width: 900px) 50vw,
         33vw"
  alt="Photo 1">


How to read the sizes attribute


Think of it as a series of media condition → slot width pairs. The browser reads them top to bottom and uses the first one that matches.


"On screens narrower than 40em, this image will be 100% of the viewport wide. On screens up to 900px, it'll be half. Otherwise, one-third."




Preloading the LCP HERO IMAGE


Lighthouse's biggest complaint about image-heavy pages is usually a slow LCP. The hero image is almost always the Largest Contentful Paint element — and the browser discovers it late, only after it has parsed and started rendering the page.


A <link rel="preload"> in the <head> tells the browser to fetch the hero image immediately, before it even starts parsing the <body>.


In your HTML, find the commented-out preload line and uncomment it:


<!-- Uncomment this line -->
<link rel="preload"
      href="https://picsum.photos/id/101/2560/1440"
      as="image">


⚠️ Only preload what's above the fold


Preloading everything defeats the purpose. Use it only for the single most important image the user sees immediately. Preloading hidden or below-fold images actually hurts performance by competing with critical resources.





Lazy Loading Below Fold Images


The grid images load immediately even though most of them are below the visible area. Adding loading="lazy" tells the browser to defer those requests until the user scrolls close to them — instant bandwidth savings on first load.


<!-- Add loading="lazy" to all grid images (NOT the hero) -->
<img
  src="https://picsum.photos/id/101/640/360"
  srcset="..."
  sizes="..."
  loading="lazy"
  alt="Photo 1">


🚫 Never put loading="lazy" on the hero/LCP image


Lazy loading the hero actively delays LCP and tanks your Lighthouse score. It belongs on images that are below the fold only.







Modern Formats with <picture>


JPEG is universal but inefficient. WebP and AVIF can deliver the same visual quality at 30–80% smaller file sizes. The <picture> element lets you offer modern formats with a JPEG fallback — the browser picks the best one it supports.


<picture>
  <!-- Best: AVIF (smallest, Chrome 85+, Firefox 93+) -->
  <source
    type="image/avif"
    srcset="
      https://picsum.photos/id/101/400/225   400w,
      https://picsum.photos/id/101/640/360   640w,
      https://picsum.photos/id/101/1280/720 1280w
    "
    sizes="(max-width: 40em) 100vw, (max-width: 900px) 50vw, 33vw">

  <!-- Better: WebP (Chrome, Firefox, Safari 14+) -->
  <source
    type="image/webp"
    srcset="
      https://picsum.photos/id/101/400/225   400w,
      https://picsum.photos/id/101/640/360   640w,
      https://picsum.photos/id/101/1280/720 1280w
    "
    sizes="(max-width: 40em) 100vw, (max-width: 900px) 50vw, 33vw">

  <!-- Fallback: JPEG for older browsers -->
  <img
    src="https://picsum.photos/id/101/640/360"
    loading="lazy"
    alt="Photo 1">
</picture>



💡 Note on picsum.photos


The Picsum CDN we're using in this exercise serves JPEG regardless of which URL you request. In a real project you'd generate WebP/AVIF files from your originals (e.g., with Squoosh, Sharp, or ImageMagick). The code structure above is correct — just be aware the actual bytes served here won't change.





Quick Reference — Before & After


Technique

What it fixes

Lighthouse impact

srcset + sizes

Sending a 1280px image to a 300px slot

↑ Performance, ↓ LCP

rel="preload"

Browser discovers hero image too late

↑↑ LCP (biggest win)

loading="lazy"

All images download on first load

↑ Speed Index, ↓ TBT

<picture> + WebP/AVIF

JPEG file size overhead

↓ total bytes transferred

object-fit: cover

Layout shift as images load

↑ CLS

aspect-ratio

Cards jumping when image loads

↑ CLS


Locked Message

bottom of page