---
title: Load above-the-fold and below-the-fold sections differently with section.index
description: >-
  Use `section.index`, `section.index0`, and `section.location` to conditionally
  apply eager loading, fetch priority, and async CSS based on each section's
  position in the page.
source_url:
  html: >-
    https://shopify.dev/docs/storefronts/themes/best-practices/performance/use-section-index
  md: >-
    https://shopify.dev/docs/storefronts/themes/best-practices/performance/use-section-index.md
api_name: liquid
---

# 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.

***

## Why

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.

***

## How

### The three position properties

1. `section.index`: 1-based position (1, 2, 3, 4...).
2. `section.index0`: 0-based position (0, 1, 2, 3...).
3. `section.location`: `template`, `static`, `content_for_index`, `preset`, a section group type such as `header`, `footer`, or `aside`, or `custom.<value>` for a custom section group.

### `section.index` is nil in three contexts

`section.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 from `theme.liquid`.
* The section is rendered in the online store editor.
* The section is rendered through the [Section Rendering API](https://shopify.dev/docs/api/section-rendering).

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:

```liquid
{% unless section.index > 2 %}
  {%- comment -%} Sections 1 and 2, and any context where section.index is nil {%- endcomment -%}
  {{ image | image_url: width: 1000 | image_tag: loading: 'eager' }}
{% else %}
  {%- comment -%} Sections 3 and later {%- endcomment -%}
  {{ image | image_url: width: 1000 | image_tag: loading: 'lazy' }}
{% endunless %}
```

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.

### `section.index` counts per location, not per page

The 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.

### Use case 1: Conditional lazy loading

Prevent lazy loading the LCP image by eagerly loading images in the first few sections:

```liquid
{% unless section.index > 3 %}
  {%- comment -%} First three sections, and nil contexts: eager load {%- endcomment -%}
  {{ image | image_url: width: 1000 | image_tag: loading: 'eager' }}
{% else %}
  {%- comment -%} Sections 4 and later: lazy load {%- endcomment -%}
  {{ image | image_url: width: 1000 | image_tag: loading: 'lazy' }}
{% endunless %}
```

### Use case 2: Conditional fetch priority

```liquid
{% if section.index == 1 %}
  {%- comment -%} First section only: high priority {%- endcomment -%}
  {{ image | image_url: width: 1000 | image_tag: loading: 'eager', fetchpriority: 'high' }}
{% elsif section.index > 3 %}
  {%- comment -%} Sections 4 and later: lazy load {%- endcomment -%}
  {{ image | image_url: width: 1000 | image_tag: loading: 'lazy' }}
{% else %}
  {%- comment -%} Sections 2 and 3, and nil contexts: eager, normal priority {%- endcomment -%}
  {{ image | image_url: width: 1000 | image_tag: loading: 'eager' }}
{% endif %}
```

### Use case 3: Conditional async CSS

```liquid
{% unless section.index > 3 %}
  {%- comment -%} Above the fold, and nil contexts: render-blocking CSS {%- endcomment -%}
  <link rel="stylesheet" href="{{ 'section.css' | asset_url }}">
{% else %}
  {%- comment -%} Below the fold: async CSS {%- endcomment -%}
  <link rel="stylesheet" href="{{ 'section.css' | asset_url }}" media="print" onload="this.media='all'">
  <noscript><link rel="stylesheet" href="{{ 'section.css' | asset_url }}"></noscript>
{% endunless %}
```

### Use `section.location`

For header-specific or footer-specific logic:

```liquid
{% if section.location == 'header' %}
  {%- comment -%} The header is always above the fold {%- endcomment -%}
  {{ logo | image_url: width: 200 | image_tag: loading: 'eager' }}
{% endif %}
```

***

## Examples

Comprehensive image loading strategy:

```liquid
{% if section.index == 1 %}
  {%- comment -%} Hero section: maximum priority {%- endcomment -%}
  {{ section.settings.image
    | image_url: width: 2000
    | image_tag:
        loading: 'eager',
        fetchpriority: 'high',
        widths: '400, 600, 800, 1000, 1200, 1600, 2000',
        sizes: '100vw',
        class: 'hero-image'
  }}
{% elsif section.index > 3 %}
  {%- comment -%} Sections 4 and later: lazy load {%- endcomment -%}
  {{ section.settings.image
    | image_url: width: 1000
    | image_tag:
        loading: 'lazy',
        widths: '400, 600, 800, 1000',
        sizes: '(min-width: 1000px) 900px, calc(100vw - 2rem)'
  }}
{% else %}
  {%- comment -%} Sections 2 and 3, and nil contexts: eager load, normal priority {%- endcomment -%}
  {{ section.settings.image
    | image_url: width: 1000
    | image_tag:
        loading: 'eager',
        widths: '400, 600, 800, 1000',
        sizes: '(min-width: 1000px) 900px, calc(100vw - 2rem)'
  }}
{% endif %}
```

***

## Testing

* Test position-dependent logic on the storefront, not in the theme editor. `section.index` is `nil` in 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.index` without handling `nil`.
* 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"`](https://web.dev/articles/fetch-priority) and non-critical resources aren't prioritized too early.
* Use the [Chrome DevTools Network panel](https://developer.chrome.com/docs/devtools/network) to verify loading strategies and resource priorities.

***

## References

* [`section.index`](https://shopify.dev/docs/api/liquid/objects/section#section-index)
* [`section.index0`](https://shopify.dev/docs/api/liquid/objects/section#section-index0)
* [`section.location`](https://shopify.dev/docs/api/liquid/objects/section#section-location)
* [`section.settings`](https://shopify.dev/docs/api/liquid/objects/section#section-settings)
* [`if`](https://shopify.dev/docs/api/liquid/tags/if) / [`elsif`](https://shopify.dev/docs/api/liquid/tags/if#if-elsif) tags
* [`image_tag`](https://shopify.dev/docs/api/liquid/filters/image_tag) filter
* [`image_url`](https://shopify.dev/docs/api/liquid/filters/image_url) filter
* [`asset_url`](https://shopify.dev/docs/api/liquid/filters/asset_url) filter
* [Announcing new Liquid features for better web performance](https://performance.shopify.com/blogs/blog/announcing-new-liquid-features-for-better-web-performance)

***
