---
title: "Grid"
description: "Lay content out on the token column grid with grid-default, and inset it by whole columns with col-mx-*."
requested_language: ar
language: en
translation_notice: "This page isn't translated yet"
url: https://docs.systhema.app/ar/next/styling/grid
version: unreleased (main)
docs_index: https://docs.systhema.app/ar/next/llms.txt
---
> This page isn't translated yet. Showing English.


The grid utilities put content on the layout grid from your tokens: the same column count, gutter and margin the design was drawn on. `grid-default` creates the grid, and `col-mx-*` insets an item by a number of columns on each side, which is how [`Section`](https://docs.systhema.app/ar/next/components/section.md) narrows its content column.

## Quick reference

<!-- generated:utilities grid -->

| Class                | Styles                                                                                                                                                     |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `grid-default`       | `display: grid;`<br>`column-gap: var(--grid-default-gap);`<br>`grid-template-columns: repeat(var(--grid-default-count), minmax(0, 1fr));`                  |
| `grid-cols-default`  | `grid-template-columns: repeat(var(--grid-default-count), minmax(0, 1fr));`                                                                                |
| `gap-grid-default`   | `gap: var(--grid-default-gap);`                                                                                                                            |
| `gap-x-grid-default` | `column-gap: var(--grid-default-gap);`                                                                                                                     |
| `gap-y-grid-default` | `row-gap: var(--grid-default-gap);`                                                                                                                        |
| `col-mx-0`           | `& { grid-column-start: 1; grid-column: span 12 / span 12; }`<br>`@media (width >= 640px) { & { grid-column: span 24 / span 24; grid-column-start: 1; } }` |
| `col-mx-1`           | `& { grid-column-start: 1; grid-column: span 12 / span 12; }`<br>`@media (width >= 640px) { & { grid-column: span 22 / span 22; grid-column-start: 2; } }` |
| `col-mx-2`           | `& { grid-column-start: 1; grid-column: span 12 / span 12; }`<br>`@media (width >= 640px) { & { grid-column: span 20 / span 20; grid-column-start: 3; } }` |
| `col-mx-3`           | `& { grid-column-start: 1; grid-column: span 12 / span 12; }`<br>`@media (width >= 640px) { & { grid-column: span 18 / span 18; grid-column-start: 4; } }` |
| `col-mx-4`           | `& { grid-column-start: 1; grid-column: span 12 / span 12; }`<br>`@media (width >= 640px) { & { grid-column: span 16 / span 16; grid-column-start: 5; } }` |
| `col-mx-5`           | `& { grid-column-start: 1; grid-column: span 12 / span 12; }`<br>`@media (width >= 640px) { & { grid-column: span 14 / span 14; grid-column-start: 6; } }` |
| `col-mx-6`           | `& { grid-column-start: 1; grid-column: span 12 / span 12; }`<br>`@media (width >= 640px) { & { grid-column: span 12 / span 12; grid-column-start: 7; } }` |

<!-- /generated -->

## Basic usage

Add `grid-default` to a container to get a CSS grid with the token column count and gutter. Combine it with [`container`](https://docs.systhema.app/ar/next/styling/container.md) to sit the grid inside the page margins, the way `Section` does. With the default tokens the grid has 12 columns on phones and 24 from `md` up; switch the preview between device widths to see the columns change.

```tsx preview iframe bleed height=200 title="grid-default container"
export default function Demo() {
  return (
    <div className="w-full py-8">
      <div className="grid-default container">
        {Array.from({ length: 24 }, (_, i) => (
          <div
            key={i}
            className="bg-theme-200 text-theme-800 grid h-20 place-items-center rounded-sm font-mono text-[10px]"
          >
            {i + 1}
          </div>
        ))}
      </div>
    </div>
  )
}
```

`grid-default` sets the column gap only. Add `gap-y-grid-default` when items wrap onto more than one row and should have the same gutter between rows, or `gap-grid-default` for both.

### Spanning columns

Items on the grid take Tailwind's `col-span-*` and `col-start-*` utilities. Count in grid columns of the current breakpoint, so a span usually needs a responsive pair: `col-span-12` fills the phone grid, `md:col-span-8` takes a third of the 24-column grid.

```tsx preview iframe bleed height=220 title="Spanning columns"
export default function Demo() {
  return (
    <div className="w-full py-8">
      <div className="grid-default container gap-y-grid-default">
        {['01', '02', '03'].map((label) => (
          <div
            key={label}
            className="bg-theme-500 col-span-12 grid h-20 place-items-center rounded-lg font-mono text-sm text-white md:col-span-8"
          >
            {label}
          </div>
        ))}
      </div>
    </div>
  )
}
```

### Insetting by columns

`col-mx-{n}` spans an item across the grid minus `n` columns on each side, from the `md` breakpoint up. Below `md` every `col-mx-*` spans the whole grid, so content stays full width on phones. `<Section padding={2}>` renders `col-mx-2` on its content column.

```tsx preview iframe bleed height=320 title="col-mx-0 to col-mx-4"
const hatch =
  'bg-[repeating-linear-gradient(315deg,var(--color-foundations-line-muted)_0_1px,transparent_0_50%)] bg-size-[10px_10px]'

const insets = ['col-mx-0', 'col-mx-1', 'col-mx-2', 'col-mx-3', 'col-mx-4']

export default function Demo() {
  return (
    <div className="w-full py-8">
      <div className={`grid-default container gap-y-grid-default rounded-lg ${hatch}`}>
        {insets.map((inset) => (
          <div
            key={inset}
            className={`bg-theme-500 grid h-10 place-items-center rounded-md font-mono text-xs text-white ${inset}`}
          >
            {inset}
          </div>
        ))}
      </div>
    </div>
  )
}
```

The classes go up to `col-mx-6` by default (see [Customizing](#customizing)).

### Using the grid tokens on your own grid

`grid-cols-default`, `gap-grid-default`, `gap-x-grid-default` and `gap-y-grid-default` set one property each from the same tokens. Use them when you build a grid with other settings, for example with Tailwind's `grid` and a row gap of your own:

```html
<div class="grid grid-cols-default gap-x-grid-default gap-y-8">…</div>
```

## Responsive and state variants

The column count, gutter and margin are `responsiveSizing` tokens, so the grid changes per breakpoint without a prefix. With the default tokens:

| Breakpoint | Columns | Gutter (`--grid-default-gap`) | Margin (`--grid-default-margin`) |
| ---------- | ------- | ----------------------------- | -------------------------------- |
| `sm`       | 12      | 16px                          | 17px                             |
| `md`       | 24      | 12px                          | 30px                             |
| `lg`       | 24      | 20px                          | 78px                             |

`col-mx-*` already switches at `md`. Prefix it to start an inset later, for example `col-mx-0 lg:col-mx-3` keeps the item full width up to `lg`. Every grid class takes breakpoint prefixes the same way (`md:grid-default`).

## Customizing

The grid reads `grid.default.count`, `grid.default.gap` and `grid.default.margin` from the `responsiveSizing` collection (see [Spacing and sizing](https://docs.systhema.app/ar/next/reference/tokens/spacing.md#grid) and [Breakpoints](https://docs.systhema.app/ar/next/reference/tokens/breakpoints.md)). Override them per breakpoint with `customTokens.responsiveSizing`:

```ts title="systhema.config.ts"
const config: SysthemaConfig = {
  customTokens: {
    responsiveSizing: {
      xl: {
        grid: { default: { count: '24', gap: '20px', margin: '142px' } },
      },
    },
  },
}
```

`col-mx-*` follows the count of each breakpoint: a breakpoint with its own count gets its own inset rules. Each other key in the tokens' `grid` group becomes a grid of its own, with `grid-<name>`, `grid-cols-<name>` and `gap-grid-<name>` classes.

The number of `col-mx-*` steps is `blocks.grid.paddingCols` (default `6`). With a 24-column grid, values up to `11` leave at least two columns:

```ts title="systhema.config.ts"
const config: SysthemaConfig = {
  blocks: {
    grid: { enabled: true, paddingCols: 8 },
  },
}
```

## Related

- [Container](https://docs.systhema.app/ar/next/styling/container.md)
- [Section](https://docs.systhema.app/ar/next/components/section.md)
- [Columns](https://docs.systhema.app/ar/next/components/columns.md)
- [Breakpoints and ranges](https://docs.systhema.app/ar/next/styling/breakpoints.md)
