Images without compromise: the business-card website pipeline that keeps LCP < 1.8 s
How to design an image pipeline that keeps your business-card website under 1.8 s LCP on mobile? Here is the full guide—from audit to deployment checklist.
A modern business-card website for a local company must load instantly on slower LTE, otherwise it loses 30-50% of potential enquiries. This guide shows you how to build an image pipeline that keeps Largest Contentful Paint (LCP) below 1.8 s while delivering spotless Core Web Vitals without heavy plugins or complex CDNs.
Who this is for and what outcome to expect
- Business-card websites, “service + city” landing pages and compact service portfolios.
 - Teams working with lightweight site generators (Astro, Eleventy) and simple CMS setups (e.g. Keystatic) who still want full control over media.
 - Goal: LCP < 1.8 s on mobile, zero CLS, stable INP without extra JavaScript.
 
Most common mistakes that destroy LCP on business-card sites
- Hero image weighing 800 KB – 2 MB in JPEG/PNG without compression or modern formats.
 - Missing 
srcsetandsizes, so even phones download the 1920 px desktop version. - Hero defined as a CSS 
background-image—no preload option, no alt text, no prioritisation. loading="lazy"on the LCP element—the browser waits until the user scrolls.- No 
width/heightattributes → layout shift and a worse CLS score. - JS sliders/carousels; in 90% of cases a single static photo + CTA is enough.
 - No performance budget: file conversion, naming and cache headers left to chance.
 
Quick audit tip: run PageSpeed Insights on mobile, open the “Diagnostics” tab and note which element is marked as LCP. If it’s your hero, follow the steps in this article.
How the browser picks an image – fundamentals you must know
srcset + sizes
srcsetprovides multiple resolution variants (e.g. 480w, 768w, 1200w).sizestells the browser how wide the image will be at each breakpoint so it can fetch the smallest suitable file.
<img
  src="/images/hero-1440.avif"
  srcset="/images/hero-480.avif 480w, /images/hero-768.avif 768w, /images/hero-1440.avif 1440w"
  sizes="(max-width: 768px) 92vw, (max-width: 1280px) 70vw, 1200px"
  alt="Modern carpentry workshop in Bytom"
  width="1200"
  height="800"
  fetchpriority="high"
  decoding="async"
  loading="eager"
>
<picture> for AVIF/WebP
Use <picture> to offer preferred formats:
<picture>
  <source type="image/avif" srcset="/images/hero-768.avif 768w, /images/hero-1440.avif 1440w" sizes="100vw">
  <source type="image/webp" srcset="/images/hero-768.webp 768w, /images/hero-1440.webp 1440w" sizes="100vw">
  <img src="/images/hero-1440.jpg" alt="Hydraulics service crew at work" width="1440" height="880" loading="eager">
</picture>
Safari on macOS/iOS still lacks full AVIF support, so keeping a WebP/JPEG fallback is essential.
Step-by-step pipeline – from audit to monitoring
1. Audit: identify the LCP element
- PageSpeed Insights (mobile): note the LCP element and its size.
 - WebPageTest → “Waterfall” tab: check how long the file takes to download and when the request starts.
 - If the hero image loads only after JavaScript, remove the bundler dependency—the image must be present in the HTML.
 
2. Conversion and file naming
- Use CLI tools (
squoosh-cli,sharp) orSquoosh.appto generate AVIF/WebP. - Naming convention: 
industry-location-size.format(e.g.plumber-bytom-768.avif). - Suggested parameters: AVIF q=0.5–0.6 (often 60-75% size reduction), WebP q=0.75.
 - Keep the original JPEG as backup and for the fallback 
src. 
3. Prepare responsive size variants
Typical set for business-card sites (px): 480, 768, 1024, 1440, 1920. That way a phone never downloads the full 1920 px asset.
4. Prioritise the hero image
- HTML: 
loading="eager",fetchpriority="high",decoding="async". - Head: preload the main variant.
 
<link
  rel="preload"
  as="image"
  href="/images/hero-1440.avif"
  imagesrcset="/images/hero-768.avif 768w, /images/hero-1440.avif 1440w"
  imagesizes="(max-width: 768px) 92vw, 1200px"
  fetchpriority="high"
>
Reminder: Preload makes sense for one critical image only. Too many preloads compete with fonts and CSS.
5. Below-the-fold images
- Add 
loading="lazy"andfetchpriority="low". decoding="async"speeds up rendering.- For galleries generate thumbnails (e.g. 320 px) and link to full-size files.
 
6. Placeholder without JavaScript
- Set 
aspect-ratioin CSS orwidth/heightin HTML. - Optionally: low-quality placeholder (LQIP) as 
background-coloror data URI (< 1 KB). - No JS = no extra hydration islands.
 
7. Maps, video, embeds
- Replace iframes with a thumbnail: click → inject the 
<iframe>afterwards. - Swap Google Maps embed for a static SVG map showing the service area + “Open route in Google Maps” button.
 
8. Cache and CDN strategy
- Host images on the same origin as the site (Astro + Cloudflare Pages/Netlify) for straightforward cache control.
 - Header: 
Cache-Control: public, max-age=31536000, immutable. - When updating assets, rename the file (
hero-v2-1440.avif). - On Cloudflare you can enable Polish + WebP/AVIF if needed—but keep your own versions for full control.
 
9. Final testing and monitoring
- Rerun PageSpeed Insights (mobile) – target green LCP (< 2.5 s) and CLS < 0.1.
 - WebPageTest with “Slow 4G + Moto G Power” profile – verify the hero downloads within the first 1.2 s.
 - Enable Real User Monitoring (e.g. GDPRmetrics or Cloudflare Web Analytics) to track LCP/INP distribution from real visits.
 
Mini case study (anonymised)
Industry: installation services in Bytom, Poland
| Metric | Before (WordPress + slider) | After (Astro + pipeline) | 
|---|---|---|
| Hero asset weight | 1.9 MB (JPEG) | 240 KB (AVIF + fallback) | 
| Largest Contentful Paint (mobile) | 3.7 s | 1.72 s | 
| Cumulative Layout Shift | 0.24 | 0.02 | 
| Contact form enquiries / month | 11 | 28 | 
Key actions: removed the slider, generated five AVIF/WebP variants, preloaded the hero, applied “click-to-load” for the map and video.
15-minute pre-launch checklist
- ✅ Hero has 
width/height,fetchpriority="high",loading="eager". - ✅ 
srcset+sizescover both mobile and desktop scenarios. - ✅ Only one preload for the hero image.
 - ✅ Every image ships with AVIF/WebP plus JPEG/PNG fallback.
 - ✅ Below-the-fold images use 
loading="lazy"andfetchpriority="low". - ✅ Gallery thumbnails ≤ 35 KB; full versions open in a lightbox or new tab.
 - ✅ Maps/video load only after user interaction.
 - ✅ 
Cache-Controlset to 1 year withimmutable. - ✅ PSI (mobile) reports LCP under 2 s, CLS < 0.1.
 - ✅ Save results in your audit sheet (handy for future redesigns).
 
FAQ – your clients will ask these questions
Is AVIF mandatory?
No, but in 2025 it brings 20-35% lower file sizes compared to WebP. If your workflow can’t export AVIF yet, start with WebP + JPEG fallback and plan the upgrade.
How many image variants should I generate?
Usually 4-5. If the section’s max width is 960 px, you don’t need a 1920 px asset.
Does fetchpriority="high" influence SEO?
Indirectly—Google measures LCP from real users. A faster hero means better CWV and improved local visibility.
img or CSS background-image?
For hero sections with copy and CTA always use <img>—easier to add alt text, preload and apply optimisation. Reserve background-image for decorative patterns.
Do alt text and lazy loading matter for rankings?
Yes. Alt text supports local SEO (“plumber Bytom”) and accessibility. loading="lazy" doesn’t harm rankings as long as you don’t apply it to the LCP element.
You now have a pipeline you can implement in a single afternoon. If you’d like me to review your site or deploy AVIF/WebP in your CMS (Keystatic, Sanity, headless WordPress), get in touch and I’ll prepare a Core Web Vitals audit tailored to your business.