> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/Shopify/horizon/llms.txt
> Use this file to discover all available pages before exploring further.

# Collection Page Features

> Powerful collection pages with filtering, infinite scroll, and flexible product grid layouts

Horizon collection pages feature advanced filtering, infinite scroll, customizable product grids, and responsive layouts optimized for browsing products.

## Key Features

* **Infinite Scroll**: Automatically load more products as users scroll
* **Filtering System**: Advanced product filtering by tags, variants, price, and more
* **Grid & Editorial Layouts**: Choose between classic grid or editorial organic layout
* **Responsive Cards**: Adjustable card sizes for mobile and desktop
* **Performance Optimized**: Uses view transitions and efficient rendering

## Collection Container

The main collection section wraps the product grid and filters:

```liquid theme={null}
<results-list
  class="section product-grid-container color-{{ section.settings.color_scheme }}"
  section-id="{{ section.id }}"
  infinite-scroll="{{ section.settings.enable_infinite_scroll }}"
>
  <div class="collection-wrapper grid gap-style">
    {% content_for 'block', type: 'filters', id: 'filters' %}
    
    {% paginate collection.products by products_per_page %}
      {% render 'product-grid',
        section: section,
        children: children,
        products: collection.products,
        paginate: paginate
      %}
    {% endpaginate %}
  </div>
</results-list>
```

## Layout Types

### Grid Layout

Classic grid with consistent card sizing:

```yaml theme={null}
layout_type: grid

product_card_size:
  options:
    - small
    - medium (default)
    - large
    - extra-large
```

### Editorial Layout

Organic layout with varying card sizes:

```yaml theme={null}
layout_type: organic
```

**Features:**

* Variable card sizes for visual interest
* Masonry-style layout
* Better for editorial/lifestyle brands

## Product Grid Rendering

### Paginated Products

```liquid theme={null}
{% assign products_per_page = 24 %}
{% if section.settings.enable_infinite_scroll == false %}
  {% assign products_per_page = section.settings.products_per_page %}
{% endif %}

{% paginate collection.products by products_per_page %}
  {% capture children %}
    {% for product in collection.products %}
      <li id="{{ section.id }}-{{ product.id }}"
          class="product-grid__item product-grid__item--{{ forloop.index0 }}"
          data-page="{{ paginate.current_page }}"
          data-product-id="{{ product.id }}"
          ref="cards[]">
        
        {% content_for 'block',
          type: '_product-card',
          id: 'product-card',
          closest.product: product
        %}
      </li>
    {% endfor %}
  {% endcapture %}
  
  {% render 'product-grid',
    section: section,
    children: children,
    products: collection.products,
    paginate: paginate,
    enable_infinite_scroll: section.settings.enable_infinite_scroll
  %}
{% endpaginate %}
```

### Product Card Attributes

<Tabs>
  <Tab title="ID">
    ```liquid theme={null}
    id="{{ section.id }}-{{ product.id }}"
    ```

    Unique identifier for each product card, used for scroll anchoring.
  </Tab>

  <Tab title="Classes">
    ```liquid theme={null}
    class="product-grid__item product-grid__item--{{ forloop.index0 }}"
    ```

    * Base class for styling
    * Index class for specific positioning
  </Tab>

  <Tab title="Data Attributes">
    ```liquid theme={null}
    data-page="{{ paginate.current_page }}"
    data-product-id="{{ product.id }}"
    ```

    Used for:

    * Pagination tracking
    * Analytics
    * Scroll restoration
  </Tab>
</Tabs>

## Infinite Scroll

Automatic product loading as users scroll:

### Configuration

```yaml theme={null}
enable_infinite_scroll:
  type: checkbox
  default: true
```

When enabled:

* Products load automatically when scrolling near bottom
* Uses Intersection Observer API
* Shows loading indicator
* Updates URL with current page

When disabled:

* Shows pagination controls
* Manual page navigation
* Configurable products per page

### Products Per Page

```yaml theme={null}
products_per_page:
  min: 8
  max: 36
  step: 4
  default: 24
  visible_if: enable_infinite_scroll == false
```

<Note>
  When infinite scroll is enabled, products per page is fixed at 24 for optimal performance.
</Note>

## Card Sizes

### Desktop Card Size

```yaml theme={null}
product_card_size:
  options:
    - small    # ~250px width
    - medium   # ~350px width (default)
    - large    # ~450px width
    - extra-large # ~600px width
  default: medium
  visible_if: layout_type == 'grid'
```

### Mobile Card Size

```yaml theme={null}
mobile_product_card_size:
  options:
    - small  # 2 columns (default)
    - large  # 1 column
  default: small
```

**CSS Implementation:**

```css theme={null}
@media screen and (max-width: 749px) {
  .product-grid[data-mobile-size='small'] {
    grid-template-columns: repeat(2, 1fr);
  }
  
  .product-grid[data-mobile-size='large'] {
    grid-template-columns: 1fr;
  }
}
```

## Grid Layout Settings

### Width Options

```yaml theme={null}
product_grid_width:
  options:
    - centered (Page width, default)
    - full-width
  default: centered
```

### Full Width on Mobile

```yaml theme={null}
full_width_on_mobile:
  type: checkbox
  default: true
  visible_if: product_grid_width != 'full-width'
```

Forces full-width grid on mobile even when using page-width on desktop.

### Gap Settings

<Tabs>
  <Tab title="Horizontal Gap">
    ```yaml theme={null}
    columns_gap_horizontal:
      min: 0
      max: 50
      step: 1
      unit: px
      default: 16
    ```

    Space between product cards horizontally.
  </Tab>

  <Tab title="Vertical Gap">
    ```yaml theme={null}
    columns_gap_vertical:
      min: 0
      max: 50
      step: 1
      unit: px
      default: 16
    ```

    Space between rows of products.
  </Tab>
</Tabs>

**CSS Variables:**

```css theme={null}
.product-grid {
  gap: var(--columns-gap-vertical) var(--columns-gap-horizontal);
}
```

### Padding Settings

<CodeGroup>
  ```yaml Left Padding theme={null}
  padding-inline-start:
    min: 0
    max: 100
    step: 1
    unit: px
    default: 0
  ```

  ```yaml Right Padding theme={null}
  padding-inline-end:
    min: 0
    max: 100
    step: 1
    unit: px
    default: 0
  ```

  ```yaml Top Padding theme={null}
  padding-block-start:
    min: 0
    max: 100
    step: 1
    unit: px
    default: 8
  ```

  ```yaml Bottom Padding theme={null}
  padding-block-end:
    min: 0
    max: 100
    step: 1
    unit: px
    default: 8
  ```
</CodeGroup>

## Filtering System

Integrated filtering block for product discovery:

```liquid theme={null}
{% content_for 'block',
  type: 'filters',
  id: 'filters',
  results: collection,
  results_size: collection.products_count
%}
```

**Filter Types:**

* Tags
* Variants (color, size, etc.)
* Price range
* Availability
* Vendor
* Product type

## URL Hash Navigation

Automatic scroll to products when using URL hash:

```javascript theme={null}
const url = new URL(window.location.href);
if (url.hash) {
  document.addEventListener('DOMContentLoaded', () => {
    const card = document.getElementById(url.hash.slice(1));
    if (card) {
      card.scrollIntoView({ behavior: 'instant' });
    }
  }, { once: true });
}
```

**Usage:**

```
/collections/all#product-123
```

Scrolls directly to product with ID 123.

## View Transitions

Smooth animations when emptying cart:

```css theme={null}
html:active-view-transition-type(empty-cart-page) {
  .cart-items-component {
    view-transition-name: cart-page-content;
  }
}

::view-transition-old(cart-page-content) {
  animation: cart-page-content-old var(--animation-speed-fast) forwards;
}
```

## Grid Column System

The collection wrapper uses a smart grid:

```css theme={null}
.collection-wrapper {
  display: grid;
  grid-template-columns: var(--grid-column--mobile);
}

@media screen and (min-width: 750px) {
  .collection-wrapper {
    grid-template-columns: var(--grid-column--desktop);
  }
}
```

**With Filters:**

```css theme={null}
--grid-column--mobile: 1fr;
--grid-column--desktop: 250px 1fr; /* Filters | Products */
```

**Without Filters:**

```css theme={null}
--grid-column--mobile: 1fr;
--grid-column--desktop: 1fr;
```

## JavaScript Module

The collection list is powered by `results-list.js`:

```liquid theme={null}
<script src="{{ 'results-list.js' | asset_url }}" type="module" fetchpriority="low"></script>
```

**Handles:**

* Infinite scroll detection
* URL parameter management
* Filter state
* Page transitions
* Analytics events

## Performance Optimizations

### Lazy Loading

```liquid theme={null}
{{ product.featured_image | image_tag: loading: 'lazy' }}
```

All product images are lazy-loaded by default.

### Fetchpriority

```liquid theme={null}
<script src="{{ 'results-list.js' | asset_url }}" fetchpriority="low"></script>
```

Non-critical JavaScript loads with low priority.

### Content Visibility

```css theme={null}
.product-card {
  content-visibility: auto;
  contain-intrinsic-size: 300px 400px;
}
```

## Accessibility

<AccordionGroup>
  <Accordion title="Skip Link">
    ```liquid theme={null}
    {% render 'skip-to-content-link',
      href: '#ResultsList',
      text: 'accessibility.skip_to_results_list'
    %}
    ```

    Allows keyboard users to skip directly to products.
  </Accordion>

  <Accordion title="ARIA Labels">
    ```liquid theme={null}
    <results-list role="region" aria-label="{{ 'accessibility.product_list' | t }}">
      <div role="list">
        <div role="listitem">...</div>
      </div>
    </results-list>
    ```
  </Accordion>

  <Accordion title="Focus Management">
    When loading new products via infinite scroll, focus is managed to prevent disorientation.
  </Accordion>
</AccordionGroup>

## Schema Configuration

```json theme={null}
{
  "name": "Collection Container",
  "enabled_on": {
    "templates": ["collection"]
  },
  "settings": [
    {
      "type": "select",
      "id": "layout_type",
      "options": [
        { "value": "grid", "label": "Grid" },
        { "value": "organic", "label": "Editorial" }
      ],
      "default": "grid"
    },
    {
      "type": "select",
      "id": "product_card_size",
      "options": [
        { "value": "small", "label": "Small" },
        { "value": "medium", "label": "Medium" },
        { "value": "large", "label": "Large" },
        { "value": "extra-large", "label": "Extra Large" }
      ],
      "default": "medium",
      "visible_if": "{{ section.settings.layout_type == 'grid' }}"
    },
    {
      "type": "select",
      "id": "mobile_product_card_size",
      "options": [
        { "value": "small", "label": "Small" },
        { "value": "large", "label": "Large" }
      ],
      "default": "small"
    },
    {
      "type": "checkbox",
      "id": "enable_infinite_scroll",
      "label": "Auto-load products",
      "default": true
    },
    {
      "type": "range",
      "id": "products_per_page",
      "label": "Products per page",
      "min": 8,
      "max": 36,
      "step": 4,
      "default": 24,
      "visible_if": "{{ section.settings.enable_infinite_scroll == false }}"
    },
    {
      "type": "select",
      "id": "product_grid_width",
      "options": [
        { "value": "centered", "label": "Page" },
        { "value": "full-width", "label": "Full" }
      ],
      "default": "centered"
    },
    {
      "type": "checkbox",
      "id": "full_width_on_mobile",
      "label": "Full width on mobile",
      "default": true
    },
    {
      "type": "range",
      "id": "columns_gap_horizontal",
      "label": "Horizontal gap",
      "min": 0,
      "max": 50,
      "step": 1,
      "unit": "px",
      "default": 16
    },
    {
      "type": "range",
      "id": "columns_gap_vertical",
      "label": "Vertical gap",
      "min": 0,
      "max": 50,
      "step": 1,
      "unit": "px",
      "default": 16
    },
    {
      "type": "color_scheme",
      "id": "color_scheme",
      "default": "scheme-1"
    }
  ]
}
```
