Maple
⌘K
DOCUMENTATIONv2.1.0

Grid Layout

Maple's grid system provides high-level abstraction over CSS Grid via shorthand syntax for columns, rows, spanning, and named areas.

Columns

The cols-* utility defines the column structure of a grid container. It supports everything from simple equal-width distributions to complex, mixed-unit layouts using a smart slash syntax.

Equal Columns

To create equal-width columns, provide the number of columns to the cols-* utility. This number automatically resolves to equal fractional units (fr), ensuring the columns distribute available space perfectly.

1fr
1fr
1fr

<!-- Equal Columns -->
<div class="gr cols-3 g-6">
  <div>1fr</div>
  <div>1fr</div>
  <div>1fr</div>
</div>
  

Fractional Columns

Use the slash syntax to create columns with different fractional ratios. For example, cols-1/2/1 creates a three-column grid where the middle column is twice as wide as the outer ones.

1fr
2fr
1fr

<!-- Fractional Columns -->
<div class="gr cols-1/2/1 g-6">
  <div>1fr</div>
  <div>2fr</div>
  <div>1fr</div>
</div>
  

Mixed Units

You can mix percentages, fractional units, and pixel-based rems in a single shorthand. For example, cols-1/4_fr_20 resolves to 25%, 1fr, and 5rem simultaneously.

25%
1fr
5rem

<!-- Mixed Units -->
<div class="gr cols-1/4_fr_20 g-6">
  <div>25%</div>
  <div>1fr</div>
  <div>5rem</div>
</div>
  
Understanding the Slash
When combining units with an underscore _, Maple treats slashes as mathematical ratios (so 1/4 becomes 25%). However, when used on their own without underscores, slashes act as structural dividers between fractional columns (so cols-1/2/1 becomes 1fr 2fr 1fr).

Column Spanning

Use the col-* utility to make an element span multiple columns. You can also use the equal sign syntax col=1/-1 for explicit start and end lines.

col-2
1
1
col-2
col=1/-1

<!-- Column Spanning -->
<div class="gr cols-3 g-6">
  <div class="col-2">Spans 2 columns</div>
  <div>1</div>
  <div>1</div>
  <div class="col-2">Spans 2 columns</div>
  <div class="col=1/-1">Spans 3 columns</div>
</div>

Rows

The rows-* utility defines the row structure of a grid container. It supports everything from simple equal-height distributions to complex, mixed-unit layouts using a smart slash syntax.

Equal Rows

To create equal-height rows, provide the number of rows to the rows-* utility. This number automatically resolves to equal fractional units (fr), ensuring the rows distribute available space perfectly.

1fr
1fr
1fr

<!-- Equal Rows -->
<div class="gr rows-3 g-6 h-80">
  <div>1fr</div>
  <div>1fr</div>
  <div>1fr</div>
</div>

Fractional Rows

Use the slash syntax to create rows with different fractional ratios. For example, rows-1/2/1 creates a three-row grid where the middle row is twice as tall as the outer ones.

1fr
2fr
1fr

<!-- Fractional Rows -->
<div class="gr rows-1/2/1 g-6">
  <div>1fr</div>
  <div>2fr</div>
  <div>1fr</div>
</div>
  

Mixed Units

You can mix percentages, fractional units, and pixel-based rems in a single shorthand. For example, rows-1/4_fr_20 resolves to 25%, 1fr, and 5rem simultaneously. (Note: The same slash and underscore rules apply here as they do in columns).

25%
1fr
5rem

<!-- Mixed Units (Rows) -->
<div class="gr rows-1/4_fr_20 g-6 h-100">
  <div>25%</div>
  <div>1fr</div>
  <div>5rem</div>
</div>

Row Spanning

Use the row-* utility to make an element span multiple rows. You can also use the equal sign syntax row=1/-1 for explicit start and end lines. This is particularly useful for creating complex dashboard layouts where some widgets need more vertical space.

row=1/-1
row-2
1
1
1
1

<!-- Row Spanning -->
<div class="
  gr
  cols-3 rows-3 g-6 h-50
">
  <div class="row=1/-1">Spans 3 rows</div>
  <div class="row-2">Spans 2 rows</div>
  <div>1</div>
  <div>1</div>
  <div>1</div>
  <div>1</div>
</div>

Areas

The areas-* utility defines named grid areas, providing a declarative way to describe the layout structure. Each string represents a row, with area names separated by underscores.

Named Areas

Assign names to grid cells and then use the area=* utility on child elements to place them. This makes layouts much easier to read and maintain than numerical spanning.

A
B
C
D

<!-- Named Areas -->
<div class="gr areas='a_b'_'c_d' g-6">
  <div class="area=a">A</div>
  <div class="area=b">B</div>
  <div class="area=c">C</div>
  <div class="area=d">D</div>
</div>

Area Spanning

To make an area span multiple columns or rows, simply repeat the area name in adjacent cells.

Header
Sidebar
Main

<!-- Area Spanning -->
<div class="gr areas='h_h'_'s_m' cols-1/4_fr g-6">
  <div class="area=h">Header</div>
  <div class="area=s">Sidebar</div>
  <div class="area=m">Main</div>
</div>

Subgrid

You can use the cols-subgrid (or cols=subgrid) and rows-subgrid (or rows=subgrid) utilities to allow nested grids to participate in the sizing of their parent grids.

1fr
Subgrid 1
Subgrid 2

<!-- Subgrid -->
<div class="gr cols-3 g-6">
  <div>1fr</div>
  <div class="gr cols-subgrid col-2">
    <div>Subgrid 1</div>
    <div>Subgrid 2</div>
  </div>
</div>

Practical Examples

The true power of Maple's grid engine lies in combining these utilities to build complex, responsive layouts with minimal markup. Here are three common UI patterns built entirely with utility classes.

Feature Cards

A standard grid of equal-width cards that responds to its container. This layout stacks cards in narrow containers and spreads them out into three columns when the container has enough room.

A

Feature A

Lorem ipsum dolor sit amet, consectetur elit.

B

Feature B

Sed do eiusmod tempor incididunt magna aliqua.

C

Feature C

Ut enim ad minim veniam, quis nostrud ullamco.

<div class="cnt">
  <div class="
    gr cols-1 sm:cols-3 g-6
    --body=oklch(0.56_0.05_260)
  ">
    <div class="
      bgc-body-100/50 p-6 rad-5 fxcol-cs
      g-4
    ">
      <div class="
        bgc-coral-150 c-coral-500
        fxrow-cc square-12
        rad-4 fs-6
      ">A</div>
      <div>
        <h4 class="fs-4 fw-600 c-body-900 mb-0">Feature A</h4>
        <p class="fs-3 c-body-600 lh-5">
          Lorem ipsum dolor sit amet, consectetur elit.
        </p>
      </div>
    </div>

    <div class="
      bgc-body-100/50 p-6 rad-5 fxcol-cs
      g-4
    ">
      <div class="
        bgc-limegreen-150 c-limegreen-500
        fxrow-cc square-12
        rad-4 fs-6
      ">B</div>
      <div>
        <h4 class="fs-4 fw-600 c-body-900 mb-0">Feature B</h4>
        <p class="fs-3 c-body-600 lh-5">
          Sed do eiusmod tempor incididunt magna aliqua.
        </p>
      </div>
    </div>

    <div class="
      bgc-body-100/50 p-6 rad-5 fxcol-cs
      g-4
    ">
      <div class="
        bgc-deepskyblue-150 c-deepskyblue-500
        fxrow-cc square-12
        rad-4 fs-6
      ">C</div>
      <div>
        <h4 class="fs-4 fw-600 c-body-900 mb-0">Feature C</h4>
        <p class="fs-3 c-body-600 lh-5">
          Ut enim ad minim veniam, quis nostrud ullamco.
        </p>
      </div>
    </div>
  </div>
</div>
Open in Playground

The Bento Dashboard

A modern, asymmetric layout perfect for dashboards or product showcases. This uses a mix of fractional columns and explicit spanning to create visual hierarchy.

Total revenue
$128,430 ▲ 12.4%
Jan Mar May Jul
Active users
2,842 ▲ 3.1%
Activity 84%
Uptime 99.9%
CPU 14%
Memory 68%
System online Updated just now
View logs
<div class="cnt">
<div
  class="
    rel tsdur-500 tsprop-all
    br-none p-4 sm:p-6 rad-6
    bshadow--6px_-6px_14px_white,6px_6px_14px_body-950/15 @dark:bshadow--6px_-6px_14px_body-950/4,6px_6px_14px_black/60 bgc-body-50
  "
>
  <div
    class="
      rel z-1 gr
      cols-2 sm:cols-4 sm:rows-3 g-3
      sm:g-4 --body=oklch(0.56_0.05_260)
    "
  >
    <!-- Revenue: two columns wide, two rows tall -->
    <div
      class="
        rel col-2 row-2 fxcol-sh
        g-4 p-4 sm:p-5 rad-4
        br brc-body-950/6 bgc-body-100/50 ts-300_all
        &:hover:-tly-1 &:hover:bshadow-0px_10px_24px_body-950/8
      "
    >
      <div class="fxcol-sh g-2">
        <span class="
          fs-2.5 sm:fs-3 lh-4 fw=600
          ls-0.08 ttf=uppercase c-body-500
        ">
          Total revenue
        </span>
        <div class="fxrow-cs fxwr=wrap g-2">
          <strong class="
            fs-7 sm:fs-9 lh-8 sm:lh-10
            fw=800 -ls-0.04 c-body-950
          ">
            $128,430
          </strong>
          <span class="
            ifxrow-cc pill
            px-2 py-0.5 fs-2.5 lh-4
            fw=700 bgc-safe-500/12 c-safe-600
          ">
            ▲ 12.4%
          </span>
        </div>
      </div>

      <div class="w-% mt-auto c-accent-500">
        <svg
          viewBox="0 0 100 32"
          preserveAspectRatio="none"
          class="block w-% h-14 sm:h-20"
        >
          <defs>
            <linearGradient id="revenue-fill" x1="0" y1="0" x2="0" y2="1">
              <stop offset="0%" stop-color="currentColor" stop-opacity="0.28" />
              <stop offset="100%" stop-color="currentColor" stop-opacity="0" />
            </linearGradient>
          </defs>
          <path
            d="M0,27 L14,25 L28,19 L42,21 L56,13 L70,15 L84,8 L100,3 L100,32 L0,32 Z"
            fill="url(#revenue-fill)"
          />
          <polyline
            points="0,27 14,25 28,19 42,21 56,13 70,15 84,8 100,3"
            fill="none"
            stroke="currentColor"
            stroke-width="2"
            stroke-linecap="round"
            stroke-linejoin="round"
            vector-effect="non-scaling-stroke"
          />
        </svg>
      </div>

      <div class="
        none sm:fxrow-cw
        g-2 fs-2.5 lh-4 c-body-500
      ">
        <span>Jan</span>
        <span>Mar</span>
        <span>May</span>
        <span>Jul</span>
      </div>
    </div>

    <!-- Active users: two columns wide -->
    <div
      class="
        rel col-2 fxcol-sh
        g-3 p-4 sm:p-5 rad-4
        br brc-body-950/6 bgc-body-100/50 ts-300_all
        &:hover:-tly-1 &:hover:bshadow-0px_10px_24px_body-950/8
      "
    >
      <div class="fxcol-sh g-1">
        <span class="
          fs-2.5 sm:fs-3 lh-4 fw=600
          ls-0.08 ttf=uppercase c-body-500
        ">
          Active users
        </span>
        <div class="fxrow-cs g-2">
          <strong class="
            fs-5 sm:fs-6 lh-7 sm:lh-8
            fw=800 -ls-0.03 c-body-950
          ">
            2,842
          </strong>
          <span class="fs-2.5 lh-4 fw=600 c-safe-600">▲ 3.1%</span>
        </div>
      </div>

      <div class="
        fxrow-ew
        g-1 h-8 w-% mt-auto
      ">
        <div class="w-% h=38% rad-1 bgc-accent-500/20"></div>
        <div class="w-% h=54% rad-1 bgc-accent-500/25"></div>
        <div class="w-% h=44% rad-1 bgc-accent-500/30"></div>
        <div class="w-% h=68% rad-1 bgc-accent-500/40"></div>
        <div class="w-% h=58% rad-1 bgc-accent-500/50"></div>
        <div class="w-% h=82% rad-1 bgc-accent-500/65"></div>
        <div class="w-% h=71% rad-1 bgc-accent-500/80"></div>
        <div class="w-% h=95% rad-1 bgc-accent-500"></div>
      </div>
    </div>

    <!-- Activity -->
    <div
      class="
        fxcol-sh
        g-3 p-4 sm:p-5 rad-4
        br brc-body-950/6 bgc-body-100/50 ts-300_all
        &:hover:-tly-1 &:hover:bshadow-0px_10px_24px_body-950/8
      "
    >
      <span class="
        fs-2.5 lh-4 fw=600 ls-0.08
        ttf=uppercase c-body-500
      ">
        Activity
      </span>
      <strong class="
        fs-5 sm:fs-6 lh-7 sm:lh-8
        fw=800 -ls-0.03 c-body-950 mt-auto
      ">
        84%
      </strong>
      <div class="
        pill h-1.5 w-% bgc-body-950/8
        of=hidden
      ">
        <div class="pill h-% w=84% bgc-accent-500"></div>
      </div>
    </div>

    <!-- Uptime -->
    <div
      class="
        fxcol-sh
        g-3 p-4 sm:p-5 rad-4
        br brc-body-950/6 bgc-body-100/50 ts-300_all
        &:hover:-tly-1 &:hover:bshadow-0px_10px_24px_body-950/8
      "
    >
      <span class="
        fs-2.5 lh-4 fw=600 ls-0.08
        ttf=uppercase c-body-500
      ">
        Uptime
      </span>
      <strong class="
        fs-5 sm:fs-6 lh-7 sm:lh-8
        fw=800 -ls-0.03 c-body-950 mt-auto
      ">
        99.9%
      </strong>
      <div class="
        pill h-1.5 w-% bgc-body-950/8
        of=hidden
      ">
        <div class="pill h-% w=99% bgc-safe-500"></div>
      </div>
    </div>

    <!-- System bar: spans every column -->
    <div
      class="
        rel col=1/-1 fxcol-sh
        g-4 p-4 sm:p-5 rad-4
        br brc-body-950/6 bgc-body-100/50 ts-300_all
        &:hover:-tly-1 &:hover:bshadow-0px_10px_24px_body-950/8
      "
    >
      <!-- pe at md keeps the memory read-out clear of the tag -->
      <div class="
        gr
        cols-1 xs:cols-2 g-4 sm:g-8
        w-% md:pe-14
      ">
        <div class="fxcol-sh g-2">
          <div class="fxrow-cw fs-2.5 lh-4">
            <span class="fw=600 ls-0.08 ttf=uppercase c-body-500">CPU</span>
            <span class="fw=700 c-body-950">14%</span>
          </div>
          <div class="
            pill h-1.5 w-% bgc-body-950/8
            of=hidden
          ">
            <div class="pill h-% w=14% bgc-safe-500"></div>
          </div>
        </div>

        <div class="fxcol-sh g-2">
          <div class="fxrow-cw fs-2.5 lh-4">
            <span class="fw=600 ls-0.08 ttf=uppercase c-body-500">Memory</span>
            <span class="fw=700 c-body-950">68%</span>
          </div>
          <div class="
            pill h-1.5 w-% bgc-body-950/8
            of=hidden
          ">
            <div class="pill h-% w=68% bgc-attention-500"></div>
          </div>
        </div>
      </div>

      <div class="
        fxrow-cs fxwr=wrap
        g-3 w-% mt-auto
      ">
        <span class="rel fxrow-cc fxs-0 square-2">
          <span class="
            abs square-2 rad-% bgc-safe-500/60
            ping
          "></span>
          <span class="square-2 rad-% bgc-safe-500"></span>
        </span>
        <div class="fxcol-ss">
          <span class="fs-3 lh-4 fw=600 c-body-900">System online</span>
          <span class="
            fs-2.5 lh-4 c-body-500
            none sm:block
          ">
            Updated just now
          </span>
        </div>
        <a
          class="
            pill
            ms-auto px-3 py-1.5 fs-2.5
            sm:fs-3 lh-4
            fw=600 ws=nowrap
            bgc-body-950 c-body-50 cursor=pointer ts-200_o
            &:hover:o-85
          "
        >
          View logs
        </a>
      </div>
    </div>
  </div>
</div>
</div>
Open in Playground

Holy Grail Layout

The classic web application shell. This example demonstrates how beautifully areas-* handles complex structural shifts, moving from a stacked mobile view to a full desktop shell without touching a single media query breakpoint outside of the classes.

<div class="cnt">
  <div class="
    gr g-4 fs-3.5 --body=oklch(0.56_0.05_260)
    areas='header'_'nav'_'main'_'sidebar'_'footer' xs:areas='header_header_header'_'nav_main_sidebar'_'footer_footer_footer' xs:cols-1/3/1
  "
  >
    
    <header class="
      area=header bgc-deepskyblue-100 c-deepskyblue-500
      p-6 rad-4 fxrow-cc
    ">Header</header>
    <nav class="
      area=nav bgc-coral-100 c-coral-500
      p-6 rad-4 fxrow-cc
    ">Navigation</nav>
    <main class="
      area=main bgc-limegreen-100 c-limegreen-500
      p-6 rad-4 fxcol-cc
    ">Main</main>
    <aside class="
      area=sidebar bgc-coral-100 c-coral-500
      p-6 rad-4 fxrow-cc
    ">Sidebar</aside>
    <footer class="
      area=footer bgc-deepskyblue-100 c-deepskyblue-500
      p-6 rad-4 fxrow-cc
    ">Footer</footer>
  </div>
</div>
Open in Playground

Refer to the underlying CSS Grid properties for granular layout control.

Grid

Items

Spacing

ESC

Start typing to search across the documentation.