Image Optimisation for 2026: A Fast JPG Workflow, Lazy Loading, and Layout Shift Prevention

Performance
Image compression workflow showing before and after file sizes with lazy loading code examples

Images account for more page weight than HTML, CSS, and JavaScript combined on the average website. The HTTP Archive reports that the median page in 2026 loads roughly 900KB of images. On image-heavy pages, that figure easily triples. Every unnecessary kilobyte is a slower page load, a worse Largest Contentful Paint score, and a user staring at a blank rectangle waiting for content to appear.

Image optimisation for static sites is a solved problem. Not a cutting-edge engineering challenge—a solved, repeatable workflow involving compression, proper HTML attributes, and a loading strategy. This guide covers format decisions, compression tooling, the HTML attributes that prevent layout shift, and loading patterns that keep pages fast without requiring a build pipeline or image CDN.

Format Decisions in 2026: JPG, WebP, and AVIF

Three image formats matter for photographic content on the web in 2026.

JPG (JPEG)

JPG remains the most pragmatic choice for most static sites. Universal browser support, universal editor support, excellent compression for photographs. A well-compressed JPG at quality 75–80 is visually indistinguishable from the original while being 80–90% smaller than the uncompressed source. JPG does not support transparency, and it uses lossy compression—always keep your originals and compress from those.

WebP

WebP delivers roughly 25–30% smaller file sizes than JPG at equivalent visual quality. Browser support is universal in 2026. For a static site where you control the image pipeline, WebP is a straightforward win if you are willing to convert your images.

The practical question is whether the size saving justifies the extra step in your workflow. If you are processing images individually in a desktop editor, adding a WebP conversion step means running each image through an additional tool. If you are batch-processing with a script or command-line tool, the overhead is negligible.

AVIF

AVIF offers even better compression than WebP—typically 30–50% smaller than JPG for photographic content. Browser support is solid in 2026, with Chrome, Firefox, Safari, and Edge all on board. However, AVIF encoding is dramatically slower than JPG or WebP. Converting a single high-resolution image can take several seconds, compared to milliseconds for JPG. For a site with hundreds of images, the encoding time adds up.

AVIF also has limited support in desktop image editing tools on Windows. Photoshop supports it, but many lighter-weight editors do not. If your workflow involves tools like Paint.NET, IrfanView, or other Windows utilities, check AVIF export support before committing to the format.

The Practical Recommendation

For most static sites built on Windows with a desktop editor: use JPG as your primary format. If you want the extra compression, serve WebP as well using the <picture> element for progressive enhancement. AVIF is worth it for image-heavy sites where the encoding time pays for itself in bandwidth savings, but for a ten-page business site with twenty images, JPG at quality 78 is perfectly adequate.

Compression Tools for Windows

You do not need a subscription service or an online tool to compress images. Several excellent free tools run locally on Windows.

Squoosh (Browser-Based, Offline-Capable)

Google’s Squoosh (squoosh.app) runs entirely in the browser. Drag an image in, adjust the quality slider, see a real-time before/after comparison, and download the result. It supports JPG, WebP, AVIF, and PNG output. It processes images locally—nothing is uploaded to a server—and is ideal for careful optimisation of hero images where you want to manually verify the quality/size trade-off.

IrfanView with Plugins

IrfanView is a free Windows image viewer that supports batch conversion and compression. Install the plugin pack to batch-process an entire folder of images: resize to a maximum width, compress to a specific JPG quality level, and output to a destination folder. Set JPG quality to 78 for photographic content, 85 for images with text or fine detail.

ImageMagick (Command Line)

For maximum control, ImageMagick’s magick command handles any conversion you need:

# Convert and compress a single image
magick input.png -quality 78 -strip output.jpg

# Batch convert all PNGs in a folder to compressed JPGs
Get-ChildItem *.png | ForEach-Object {
  magick $_.FullName -quality 78 -strip ($_.BaseName + ".jpg")
}

# Resize to max 1600px wide and compress
magick input.jpg -resize 1600x -quality 78 -strip output.jpg

The -strip flag removes EXIF metadata (camera info, GPS coordinates, colour profiles you do not need on the web), which typically saves 10–50KB per image. For privacy-conscious sites, stripping metadata also removes location data that users might not want published.

Width and Height: The CLS Fix That Takes Two Minutes

Every <img> tag needs width and height attributes. Full stop. This is the single most impactful thing you can do for Cumulative Layout Shift, and it is embarrassingly simple.

Without dimensions:

<img src="/images/team-photo.jpg" alt="Our team at the 2025 conference">

The browser encounters this tag during parsing. It knows an image will appear here, but it does not know the image’s dimensions until it downloads (or at least receives the header bytes). So it allocates zero space. When the image loads, the browser expands the element to fit, pushing everything below it down the page. That downward push is a layout shift, and it counts against your CLS score.

With dimensions:

<img src="/images/team-photo.jpg" alt="Our team at the 2025 conference" width="1200" height="800">

Now the browser knows the aspect ratio immediately. Even before the image downloads, it reserves a 3:2 rectangle. Content below the image is positioned correctly from the first render. When the image loads, it fills the reserved space without moving anything.

Combined with this CSS, the image is responsive and shift-free:

img {
  max-width: 100%;
  height: auto;
}

The max-width: 100% prevents the image from exceeding its container. The height: auto maintains the aspect ratio. The browser uses the width and height attributes to calculate the aspect ratio for space reservation, and the CSS controls the actual rendered size. This combination has been the correct approach since 2020 and nothing has changed.

Finding and Adding Missing Dimensions

If you have an existing site with images missing dimensions, the fastest approach is a browser-based audit:

  1. Open each page in Chrome.
  2. Open DevTools, go to the Console.
  3. Run: document.querySelectorAll('img:not([width])').forEach(img => console.log(img.src, img.naturalWidth, img.naturalHeight)).
  4. This lists every image missing a width attribute along with its actual dimensions.
  5. Add the attributes to your HTML.

For sites built with DFM2HTML, the editor includes image dimensions when you insert images through the design interface. The exported HTML includes width and height attributes matching the placed image’s dimensions. If you have manually edited the HTML after export and removed these attributes, add them back. The features page describes how DFM2HTML handles image sizing in its generated output.

Lazy Loading: Load What’s Visible, Defer the Rest

The loading="lazy" attribute on <img> tags tells the browser to defer loading images that are not currently in or near the viewport. As the user scrolls, images load just before they come into view. This reduces initial page weight, speeds up the first render, and saves bandwidth for users who never scroll to the bottom of the page.

<img
  src="/images/portfolio-item-7.jpg"
  alt="Website redesign for a local bakery"
  width="800"
  height="600"
  loading="lazy"
>

Browser support is universal in 2026. Chrome, Firefox, Safari, and Edge all honour the attribute. There is no JavaScript required, no Intersection Observer to configure, no polyfill to include. One attribute, immediate benefit.

Where NOT to Use Lazy Loading

Do not lazy-load images that are visible in the initial viewport—the “above the fold” content. Your hero image, your logo, any images that appear without scrolling should load immediately. Lazy loading them actually hurts LCP because the browser defers the download, then has to fetch the image when it realises it is in the viewport. That round trip adds latency to your largest contentful paint.

The rule is simple: images above the fold get no loading attribute (or loading="eager", which is the default). Images below the fold get loading="lazy".

<!-- Above the fold: hero image, loads immediately -->
<img
  src="/images/hero.jpg"
  alt="Workshop storefront"
  width="1600"
  height="900"
  fetchpriority="high"
>

<!-- Below the fold: portfolio items, load lazily -->
<img
  src="/images/project-1.jpg"
  alt="E-commerce site redesign"
  width="800"
  height="600"
  loading="lazy"
>

fetchpriority for the LCP Image

The fetchpriority attribute tells the browser how important an image download is relative to other resources. For your LCP image, set fetchpriority="high". This ensures the browser prioritises downloading this image immediately, even while parsing the rest of the HTML. Use it on exactly one image per page—the LCP candidate. Applying it to multiple images defeats the purpose.

Responsive Images with srcset

If your site serves the same large image to both desktop and mobile users, mobile visitors download far more data than they need. A 1600-pixel-wide hero image displayed on a 375-pixel-wide phone screen wastes over 75% of the downloaded pixels.

The srcset attribute lets you provide multiple sizes of the same image. The browser picks the most appropriate size based on the device’s screen width and pixel density:

<img
  src="/images/hero-800.jpg"
  srcset="
    /images/hero-400.jpg 400w,
    /images/hero-800.jpg 800w,
    /images/hero-1200.jpg 1200w,
    /images/hero-1600.jpg 1600w
  "
  sizes="(max-width: 600px) 100vw, (max-width: 1200px) 80vw, 1600px"
  alt="Workshop interior panorama"
  width="1600"
  height="900"
>

The sizes attribute tells the browser how wide the image will be rendered at various viewport widths. Combined with srcset, the browser calculates which image file to download. A phone with a 375px viewport and 2x pixel density needs 750 pixels of image data—it downloads hero-800.jpg instead of hero-1600.jpg, saving significant bandwidth.

When srcset Is Worth the Effort

For a five-page business site with a handful of images, srcset may not be justified. For image-heavy sites—portfolios, galleries, product listings—it is worth it. The bandwidth savings for mobile users are substantial, and the improved LCP on mobile directly affects Core Web Vitals scores.

If you are publishing a folder-based static site, you generate the image variants yourself. Name them consistently (hero-400.jpg, hero-800.jpg, etc.) and place them in your images folder. No build pipeline required.

The Picture Element for Format Fallbacks

If you decide to serve WebP or AVIF alongside JPG, the <picture> element provides the fallback mechanism:

<picture>
  <source srcset="/images/hero.avif" type="image/avif">
  <source srcset="/images/hero.webp" type="image/webp">
  <img
    src="/images/hero.jpg"
    alt="Workshop interior"
    width="1600"
    height="900"
    loading="lazy"
  >
</picture>

The browser evaluates the <source> elements top to bottom and uses the first format it supports. Note that width, height, alt, loading, and fetchpriority attributes go on the <img> element inside <picture>, not on the <picture> element itself.

A Complete Image Optimisation Workflow

Here is the step-by-step workflow for every image you add to a static site:

  1. Start with the highest quality source. Original camera output, full-resolution design export, or the highest quality version available. Never optimise from an already-compressed image.

  2. Resize to the maximum display size. If your layout never displays the image wider than 1600 pixels, resize the source to 1600px wide. There is no benefit to shipping a 4000px image that the CSS constrains to 1600px.

  3. Compress. JPG quality 75–80 for photographs, 80–85 for images with text or fine detail. Strip metadata. Target 80–150KB for hero images, 30–80KB for content images, under 20KB for thumbnails.

  4. Generate responsive variants if using srcset. Common widths: 400, 800, 1200, 1600. Each gets the same compression treatment.

  5. Convert to WebP or AVIF if desired. Use the <picture> element for format fallback.

  6. Add to HTML with all attributes. src, alt, width, height, loading (lazy for below-fold, omit for above-fold), fetchpriority (high for the LCP image only).

  7. Test. Open in Chrome, run a Lighthouse audit or check PageSpeed Insights. Verify that CLS is zero for the page, LCP is under 2.5 seconds, and image file sizes are reasonable.

This workflow is manual, deliberate, and fast. For a typical page with five images, the entire process takes fifteen minutes. No build tool, no image CDN subscription, no framework plugin—just files on disk referenced by HTML attributes.

How DFM2HTML Handles Images

DFM2HTML inserts images with width and height attributes set from the image dimensions at design time. When you place an image in the visual editor, the exported HTML includes the correct width and height values, which provides the CLS prevention by default without manual attribute entry.

The template gallery shows layouts with properly sized image placeholders. When you replace the placeholder images with your own content and maintain the same aspect ratio, the layout shift prevention carries over. If you change the aspect ratio, update the width and height attributes to match your new image dimensions.

For compression and format conversion, DFM2HTML defers to external tools—the editor focuses on producing correct HTML markup, and you apply your chosen compression workflow to the image files before or after export.

Common Mistakes and Quick Fixes

Mistake: Using PNG for photographs. PNG is lossless and produces huge files for photographic content—5–10x larger than compressed JPG. Use PNG only for images needing transparency or flat colours (logos, icons, diagrams).

Mistake: Setting JPG quality to 100. Quality 100 produces files nearly as large as the uncompressed source. The sweet spot is 75–80.

Mistake: Lazy loading the hero image. This delays your LCP element. The hero image should load immediately with fetchpriority="high".

Mistake: Using CSS background-image for content images. Background images cannot have alt text, cannot use width/height for CLS prevention, and cannot use loading="lazy" or srcset. Use <img> tags for all content images.

Mistake: Omitting alt text. Every content image needs descriptive alt text. Decorative images get alt="" (empty, not missing).

Measuring the Impact

After applying this workflow, measure the results. Run PageSpeed Insights on your key pages and compare to your baseline scores. The metrics that should improve:

  • LCP: Should drop significantly if hero images were previously uncompressed.
  • CLS: Should drop to zero or near-zero if you added missing width/height attributes.
  • Total page weight: Should decrease substantially. A page that loaded 2MB of images might load 400KB after compression and lazy loading.

The Core Web Vitals guide covers the broader measurement and prioritisation process. Image optimisation is typically step one in that process because it produces the largest improvement for the least effort. The tutorials index links to further performance topics if CSS delivery or JavaScript optimisation is your next target.

Images are the heaviest part of your pages. Compress them, size them, dimension them, and load them strategically. The workflow is straightforward, the tools are free, and the impact is immediate.


← Back to Tutorials Download DFM2HTML