Run your Shopify homepage through PageSpeed Insights and there’s a good chance Largest Contentful Paint (LCP) is the metric dragging your Core Web Vitals score into “poor” or “needs improvement” territory. Nine times out of ten, when we look at why, the answer is sitting right at the top of the page: the hero banner.
LCP measures how long it takes for the largest visible element on the page to finish rendering, on most Shopify homepages, that’s the full-width hero image or slider sitting above the fold. It sounds like a simple fix (“just compress the image”), but on Shopify specifically, hero banners tend to accumulate several compounding problems at once: oversized source files, incorrect lazy-loading, render-blocking CSS and JS ahead of the image, and slider apps that add their own overhead before the image can even start loading.
This post goes deeper than “optimise your images” advice. It’s specifically about why the hero section is the LCP element on most Shopify stores, what’s actually happening technically when it loads slowly, and the concrete fixes available within Shopify’s theme architecture and Liquid image filters, not a generic web performance checklist with Shopify’s name attached.
Why the hero banner is almost always your LCP element
LCP looks at the single largest element rendered within the viewport during initial page load, typically an image, a background image set via CSS, or occasionally a large block of text. On a typical Shopify homepage, the layout is: header, then a full-bleed hero image or slider taking up most or all of the first screen, then collections and product grids below.
That hero image is usually the largest pixel area on the page by a wide margin, which makes it the LCP candidate almost by default. Sliders make this worse, not better, a carousel doesn’t just have one large image, it has two, three or more, and the browser still has to fully load and render the first visible slide before LCP is recorded. If that first slide is a 4000px-wide unoptimised JPEG or PNG exported straight from a designer’s file, you’ve already lost the metric before any other part of the page even starts rendering.
This is worth being clear about: LCP isn’t really “how fast is my whole page.” It’s “how fast does the single biggest thing above the fold appear.” On Shopify, that focuses almost all of the optimisation work on one section of one template.
The four ways Shopify hero sections typically break LCP
1. Oversized, unoptimised source images
This is the most common cause and the easiest to verify. Merchants (or their designers) frequently upload hero images at print-ready resolution, sometimes 3000-5000px wide, several megabytes in file size, because the file “looks good” in the theme editor preview. Shopify doesn’t reject oversized uploads; it will happily serve a 4MB PNG if that’s what’s in the Files section.
Shopify does automatically generate resized versions of images through its CDN when a theme requests them correctly (more on this below), but if the theme section or a page-builder app is hardcoding the original image URL rather than requesting a properly sized version, the browser downloads the full original file regardless of how large the visitor’s screen actually is.
2. Lazy-loading applied to the wrong image
Lazy-loading is one of the most misapplied performance techniques on Shopify. The logic of loading="lazy" is to defer loading images that are below the fold, off-screen, until the user is about to scroll to them, which is genuinely useful for product grids, collection pages, and anything further down the page.
Applied to the hero image, it’s actively harmful. Because the hero is the first thing in the viewport, loading="lazy" doesn’t save any real screen-rendering time, the image needs to display immediately, but it can add extra latency by deferring the resource request in the browser’s fetch priority queue, delaying exactly the image LCP is measuring. Some themes apply loading="lazy" uniformly across every <img> tag in a section as a blanket “performance” setting, without excluding the first slide or the above-the-fold hero. The fix is that above-the-fold hero images should generally load eagerly (no lazy-loading attribute, or explicitly loading="eager"), and ideally be flagged with fetchpriority="high" so the browser prioritises fetching them immediately.
3. Render-blocking CSS and JS ahead of the image
Even a perfectly optimised hero image can’t paint until the browser has finished processing any render-blocking resources that come before it in the document. On Shopify themes, this usually means:
- Custom fonts loaded via
@importor blocking<link>tags in theme.liquid, which the browser has to fetch and parse before it can safely paint text and, in some layouts, before it triggers layout for elements below. - App-injected JavaScript (particularly from marketing, personalisation, or slider apps) loaded synchronously in the
<head>, which blocks the parser until it downloads and executes. - Large, unminified CSS files loaded in full for every page, even though only a fraction of the rules apply to the homepage hero.
None of these directly touch the image file, but all of them push back the point at which the browser is free to render it, which pushes back LCP.
4. Slider and carousel apps compounding the problem
Hero sliders are a recurring theme in slow Shopify homepages, and it’s rarely the concept of a slider that’s the problem, it’s the implementation. Many slider apps work by loading their own JavaScript library, initialising a DOM structure for all slides (not just the visible one), and only then revealing the first slide, sometimes with a fade-in transition that further delays when the image is considered “painted” for LCP purposes.
Compounding that, some slider apps load all slide images near-simultaneously rather than prioritising the first visible one, competing for the same bandwidth and connection slots the hero image needs. If a merchant genuinely needs a rotating hero, a native theme-based slider that treats the first slide as a priority-loaded image (rather than an app injecting a generic carousel library) will almost always outperform a heavier third-party app.
Getting Shopify to serve properly sized, responsive images
This is where Shopify’s own tooling actually helps, if the theme is using it correctly. Shopify’s Liquid image_url filter (the modern replacement for the older img_url filter) lets a theme request a specific rendered size from Shopify’s CDN, rather than serving the original upload:
{{ section.settings.hero_image | image_url: width: 1600 }}
Combined with srcset and sizes attributes, a well-built theme section can offer the browser several width options and let it choose the most appropriate one for the visitor’s actual viewport and pixel density:
<img
src="{{ section.settings.hero_image | image_url: width: 1600 }}"
srcset="
{{ section.settings.hero_image | image_url: width: 750 }} 750w,
{{ section.settings.hero_image | image_url: width: 1100 }} 1100w,
{{ section.settings.hero_image | image_url: width: 1600 }} 1600w,
{{ section.settings.hero_image | image_url: width: 2000 }} 2000w
"
sizes="100vw"
alt="{{ section.settings.hero_image.alt | escape }}"
width="{{ section.settings.hero_image.width }}"
height="{{ section.settings.hero_image.height }}"
loading="eager"
fetchpriority="high"
>
A mobile visitor on a narrow viewport should never be downloading the same 2000px-wide file as a desktop visitor on a large monitor, that’s the entire point of srcset. Explicit width and height attributes also matter beyond LCP: they let the browser reserve the correct space before the image loads, which prevents layout shift (a separate Core Web Vital, Cumulative Layout Shift) as the page renders.
A practical checklist for diagnosing hero-image LCP problems
- Run the homepage through PageSpeed Insights or Chrome DevTools’ Lighthouse panel and confirm the hero image is flagged as the LCP element (it will name the specific element).
- Check the actual file size and pixel dimensions of the hero image being served, right-click, inspect, and look at the requested URL’s width parameter.
- Confirm the hero image is not carrying
loading="lazy"or any deferred-loading class/attribute. - Check whether
fetchpriority="high"is set on the hero image (newer themes support this; older or heavily customised themes often don’t). - Review the
<head>for render-blocking third-party scripts loading before the main content, anything withoutasyncordeferon a script tag is a candidate. - If using a slider app, test disabling it temporarily (or switching to a static hero) and re-measure LCP to isolate how much of the delay it’s responsible for.
- Confirm
srcset/sizesare present so mobile visitors aren’t downloading desktop-sized images.
When to bring in a specialist
Some of this is a genuinely quick fix, compressing an oversized image or removing a stray loading="lazy" attribute can be done in an afternoon by anyone comfortable in the theme editor. Where it gets harder is when the LCP delay is coming from a combination of causes at once: a heavy slider app, render-blocking scripts from two or three different marketing tools, and a theme that wasn’t built with srcset support to begin with. Untangling which factor is contributing how much delay usually needs proper waterfall analysis rather than guesswork.
That’s exactly the kind of diagnostic work covered by our Shopify performance optimisation service, identifying which specific resources are delaying your LCP element, fixing the theme code and image delivery, and re-testing against real Core Web Vitals data rather than a single Lighthouse run.
FAQ
What is a good LCP score for a Shopify store?
Google’s threshold for a “good” LCP is 2.5 seconds or less, measured at the 75th percentile of real visitor data (field data), not a single lab test. Between 2.5 and 4 seconds is “needs improvement,” and anything above 4 seconds is classified as “poor.”
Why does my hero image show as the LCP element even though it’s already compressed?
Compression alone doesn’t fix everything, if the image is still being served at a larger resolution than the visitor’s screen needs, is lazy-loaded, or is delayed by render-blocking scripts and fonts loading first, LCP will still be slow even with a reasonably sized file.
Should I remove my homepage slider entirely to fix LCP?
Not necessarily. A single, well-optimised hero image or a lightweight, theme-native slider that prioritises the first slide can perform fine. The issue is usually the specific app implementation, not the concept of a slider, testing with it temporarily disabled will tell you how much it’s actually contributing to the delay.
Does Shopify’s CDN automatically optimise my images?
Shopify’s CDN can serve resized, compressed versions of an image when a theme correctly requests them via the image_url filter with a specified width. It does not automatically fix things if the theme is hardcoding the original file’s URL, or if the source file itself is unnecessarily large to begin with.
Is LCP the only Core Web Vital I should worry about on Shopify?
No, Cumulative Layout Shift (visual stability) and Interaction to Next Paint (responsiveness) both matter too. But LCP is the one most directly tied to the hero section, and it’s usually the first one worth fixing because the cause is so often isolated to a single template section.
Ready to see your real Core Web Vitals data?
If you’re not sure whether it’s your hero image, a slider app, or something else entirely delaying your LCP, a Shopify audit will pinpoint the exact cause using real performance data rather than guesswork.