FreeFeaturedAnimated

Bento Grid

Editorial bento layout for benefits, features, or value props.

#bento#grid#features#editorial#blocks

Live preview

See it in action.

Fully interactive, drag, click, scroll inside the frame, toggle to mobile.

About this section

Apple-style bento with three cell sizes (1/3, 2/3, full row), optional background image per cell, and graceful single-column collapse on mobile. Block-driven.

Install in 90 seconds

  1. 01

    Create /sections/modblo-bento-grid.liquid.

  2. 02

    Paste the code and save.

  3. 03

    Add the section, then add Tile blocks. Choose a size per tile.

The code

This is the file you'll paste into your theme.

modblo-bento-grid.liquid
{%- comment -%} modblo. Bento Grid {%- endcomment -%}
<section class="modblo-bento" data-section-id="{{ section.id }}"
  style="--modblo-bg: {{ section.settings.bg }}; --modblo-fg: {{ section.settings.fg }};">
  <div class="modblo-bento__inner page-width">
    {%- if section.settings.heading != blank -%}
      <h2 class="modblo-bento__heading">{{ section.settings.heading }}</h2>
    {%- endif -%}
    {%- if section.settings.subheading != blank -%}
      <p class="modblo-bento__sub">{{ section.settings.subheading }}</p>
    {%- endif -%}

    <div class="modblo-bento__grid">
      {%- for block in section.blocks -%}
        <article class="modblo-bento__cell modblo-bento__cell--{{ block.settings.size }}" {{ block.shopify_attributes }}
          {%- if block.settings.bg %} style="--modblo-cell: {{ block.settings.bg }}"{% endif %}>
          {%- if block.settings.image != blank -%}
            {{ block.settings.image | image_url: width: 1200 | image_tag:
              loading: 'lazy', widths: '400,800,1200', class: 'modblo-bento__img' }}
          {%- endif -%}
          <div class="modblo-bento__body">
            {%- if block.settings.eyebrow != blank -%}
              <p class="modblo-bento__eyebrow">{{ block.settings.eyebrow }}</p>
            {%- endif -%}
            <h3>{{ block.settings.title }}</h3>
            {%- if block.settings.text != blank -%}
              <p>{{ block.settings.text }}</p>
            {%- endif -%}
            {%- if block.settings.cta_label != blank -%}
              <a href="{{ block.settings.cta_link }}" class="modblo-bento__cta">
                {{ block.settings.cta_label }} →
              </a>
            {%- endif -%}
          </div>
        </article>
      {%- endfor -%}
    </div>
  </div>
</section>

<style>
  .modblo-bento { background: var(--modblo-bg, #fafafa); color: var(--modblo-fg, #0b0b0c); padding: clamp(64px,10vw,128px) 0; }
  .modblo-bento__inner { max-width: 1200px; margin: 0 auto; padding: 0 24px; }
  .modblo-bento__heading { font-size: clamp(28px,4vw,44px); letter-spacing: -.025em; margin: 0 0 12px; max-width: 640px; }
  .modblo-bento__sub { font-size: 17px; opacity: .72; max-width: 560px; margin: 0 0 36px; }
  .modblo-bento__grid {
    display: grid;
    grid-template-columns: repeat(6, 1fr);
    grid-auto-rows: minmax(180px, auto);
    gap: 16px;
  }
  .modblo-bento__cell {
    background: var(--modblo-cell, color-mix(in oklab, var(--modblo-fg) 4%, var(--modblo-bg)));
    border: 1px solid color-mix(in oklab, var(--modblo-fg) 8%, transparent);
    border-radius: 20px; padding: 24px;
    position: relative; overflow: hidden;
    display: flex; flex-direction: column; justify-content: flex-end;
    transition: transform .35s cubic-bezier(.16,1,.3,1), border-color .25s;
    grid-column: span 2;
  }
  .modblo-bento__cell:hover { transform: translateY(-3px); border-color: color-mix(in oklab, var(--modblo-fg) 16%, transparent); }
  .modblo-bento__cell--lg { grid-column: span 4; }
  .modblo-bento__cell--xl { grid-column: span 6; }
  .modblo-bento__img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: .9; }
  .modblo-bento__body { position: relative; z-index: 1; }
  .modblo-bento__cell:has(.modblo-bento__img) .modblo-bento__body {
    color: #fff; text-shadow: 0 1px 2px rgba(0,0,0,.3);
  }
  .modblo-bento__eyebrow { text-transform: uppercase; letter-spacing: .14em; font-size: 11px; opacity: .65; margin: 0 0 6px; font-weight: 600; }
  .modblo-bento__cell h3 { font-size: 20px; letter-spacing: -.015em; margin: 0; }
  .modblo-bento__cell p { font-size: 14px; opacity: .8; line-height: 1.5; margin: 8px 0 0; }
  .modblo-bento__cta { display: inline-block; margin-top: 14px; font-size: 13px; font-weight: 600; color: inherit; text-decoration: none; }

  @media (max-width: 768px) {
    .modblo-bento__grid { grid-template-columns: 1fr; }
    .modblo-bento__cell, .modblo-bento__cell--lg, .modblo-bento__cell--xl { grid-column: span 1; }
  }
</style>

{% schema %}
{
  "name": "Bento Grid",
  "tag": "section",
  "settings": [
    { "type": "text", "id": "heading", "label": "Heading", "default": "Built for the way modern brands ship." },
    { "type": "textarea", "id": "subheading", "label": "Subheading" },
    { "type": "color", "id": "bg", "label": "Background", "default": "#fafafa" },
    { "type": "color", "id": "fg", "label": "Foreground", "default": "#0b0b0c" }
  ],
  "blocks": [{
    "type": "tile",
    "name": "Tile",
    "settings": [
      { "type": "select", "id": "size", "label": "Size",
        "options": [
          { "value": "sm", "label": "Small (1/3)" },
          { "value": "lg", "label": "Wide (2/3)" },
          { "value": "xl", "label": "Full row" }
        ], "default": "sm" },
      { "type": "text", "id": "eyebrow", "label": "Eyebrow" },
      { "type": "text", "id": "title", "label": "Title", "default": "Performance-first" },
      { "type": "textarea", "id": "text", "label": "Text" },
      { "type": "image_picker", "id": "image", "label": "Background image (optional)" },
      { "type": "color", "id": "bg", "label": "Cell background" },
      { "type": "text", "id": "cta_label", "label": "CTA label" },
      { "type": "url", "id": "cta_link", "label": "CTA link" }
    ]
  }],
  "max_blocks": 12,
  "presets": [{
    "name": "Bento Grid",
    "blocks": [
      { "type": "tile", "settings": { "size": "lg", "title": "One marketplace, every section." } },
      { "type": "tile", "settings": { "size": "sm", "title": "99 Lighthouse" } },
      { "type": "tile", "settings": { "size": "sm", "title": "Native Liquid" } },
      { "type": "tile", "settings": { "size": "sm", "title": "Mobile-first" } },
      { "type": "tile", "settings": { "size": "lg", "title": "Built by ex-Shopify devs." } }
    ]
  }]
}
{% endschema %}

What you can customize

Every setting below shows up in the Shopify theme editor. Change them without touching code.

SettingTypeDefault

Heading

heading

Text,

Subheading

subheading

Long text,

Background

bg

Color picker,

Foreground

fg

Color picker,

SEO and accessibility notes

  • Each tile is a real <article> with semantic <h3>.
  • :has() selector toggles overlay text styling when an image is present, no JS.