Load above-the-fold and below-the-fold sections differently with section. index
Use section.index, section.index0, and section.location Liquid properties to conditionally optimize loading strategies and CSS application based on section position.
Before these properties, theme developers couldn't determine section position, leading to common anti-patterns: lazy loading all images, including the LCP image; async loading all CSS, including above-the-fold CSS; and no fetch priority hints, because the first section couldn't be identified. These properties enable position-aware optimization that prevents lazy loading the LCP image while still lazy loading images outside the initial viewport, and loads CSS for content visible in the initial viewport synchronously while loading CSS for content outside the initial viewport asynchronously.
Anchor to The three position propertiesThe three position properties
section.index: 1-based position (1, 2, 3, 4...).section.index0: 0-based position (0, 1, 2, 3...).section.location:template,static,content_for_index,preset, a section group type such asheader,footer, oraside, orcustom.<value>for a custom section group.
Anchor to [object Object], is nil in three contextssection.index is nil in three contexts
section.index is nil in three contextssection.index and section.index0 are nil when the section isn't rendered from a positioned list:
- The section is rendered as a static section with
{% section 'name' %}, such as fromtheme.liquid. - The section is rendered in the online store editor.
- The section is rendered through the Section Rendering API.
This matters because comparisons against nil are falsey in Liquid. nil <= 2 doesn't raise an error and doesn't evaluate to true. It evaluates to false, so a condition written as {% if section.index <= 2 %} takes its else branch. If the else branch lazy-loads the image, then your LCP image is lazy-loaded in the online store editor. If there's no else branch, then the image isn't rendered at all.
Write the condition so that nil falls to the safe side. Test the below-the-fold case as a positive section.index > N comparison, and let every other case, including nil, fall through to the eager or synchronous branch:
The image_tag filter's own default already works this way. When you don't pass a loading argument, image_tag loads the image eagerly for the first three sections and whenever section.index0 is nil. Hand-written gating that compares section.index with <= produces the opposite behavior in exactly the contexts where the built-in default is careful.
Anchor to [object Object], counts per location, not per pagesection.index counts per location, not per page
section.index counts per location, not per pageThe counter restarts at 1 for each rendered location. A section group, a JSON template, and content_for_index each maintain their own numbering, so the first section of the footer group and the first section of the template are both index 1. Disabled sections don't consume an index.
Because of this, section.index == 1 means "first in its location," not "first on the page." Combine it with section.location when you need page-level position.
Anchor to Use case 1: Conditional lazy loadingUse case 1: Conditional lazy loading
Prevent lazy loading the LCP image by eagerly loading images in the first few sections:
Anchor to Use case 2: Conditional fetch priorityUse case 2: Conditional fetch priority
Anchor to Use case 3: Conditional async CSSUse case 3: Conditional async CSS
Anchor to Use ,[object Object]Use section.location
section.locationFor header-specific or footer-specific logic:
Anchor to ExamplesExamples
Comprehensive image loading strategy:
Anchor to TestingTesting
- Test position-dependent logic on the storefront, not in the theme editor.
section.indexisnilin the editor, so reordering sections there never changes the value and can't verify the logic. - Reorder the sections in the editor, save, and then load the storefront preview to check that the loading logic adjusts correctly.
- Open the theme editor and confirm that every image still renders. A missing image there means a condition compares
section.indexwithout handlingnil. - Test across page types, such as home, product, and collection pages, because the index restarts at 1 in each section group and template.
- Check the Priority column in the Network panel to verify that the LCP image has
fetchpriority="high"and non-critical resources aren't prioritized too early. - Use the Chrome DevTools Network panel to verify loading strategies and resource priorities.
Anchor to ReferencesReferences
section.indexsection.index0section.locationsection.settingsif/elsiftagsimage_tagfilterimage_urlfilterasset_urlfilter- Announcing new Liquid features for better web performance