# Grid

> Equal columns, or CSS-like tracks with spans. A native Pyzed component for Python desktop GUIs, with a live preview, code examples and its API.

Source: https://albakore.github.io/pyzed/library/grid/

:::tip[In plain words]
Arranges things in rows and columns, like tiles on a wall.
:::

Lays out children in a grid. With `columns=3` the columns are equal, and `max_width` fits as many as possible. With track lists (`columns=[200, "1fr", "auto"]`) it works like a CSS grid, and `pz.cell(child, column=, row=, column_span=, row_span=)` places a child explicitly.

`pz.grid` · Category: [Layout](https://albakore.github.io/pyzed/library/#layout) · [Full reference →](https://albakore.github.io/pyzed/reference/widgets/#grid)

**Code:**

```python
box = lambda text, w=90, h=44: pz.container(ui.label(text), center=True, width=w, height=h, bg=pz.theme.current().element, radius=6)
pz.container(pz.grid([box(str(i), w="fill") for i in range(1, 9)], columns=4, spacing=8), width=440)
```

:::note[New]
This component was added recently. Tell us how it works for you in the [issue tracker](https://github.com/albakore/pyzed/issues).
:::

## When to use

- For galleries, dashboards and page layouts with a header, sidebar and content.

## Usage

```python
import pyzed as pz
from pyzed import ui

box = lambda text, w=90, h=44: pz.container(ui.label(text), center=True, width=w, height=h, bg=pz.theme.current().element, radius=6)
pz.container(pz.grid([box(str(i), w="fill") for i in range(1, 9)], columns=4, spacing=8), width=440)
```

## Variants

:::note[About these captures]
Each capture is recorded by pyzed itself, off-screen at 2x, in One Dark or One Light to match this site's theme, and cropped to the component so it shows at its real size. The pointer hovers, presses or types into it; a component that does not react to the pointer cycles through a few themes. With reduced motion you see the first frame. Open **Code** under a capture to see the snippet that draws it; free names such as `on_save` stand for your own callbacks.
:::

### Columns

```python
box = lambda text, w=90, h=44: pz.container(ui.label(text), center=True, width=w, height=h, bg=pz.theme.current().element, radius=6)
pz.container(pz.grid([box(str(i), w="fill") for i in range(1, 5)], columns=2, spacing=8, height=44), width=220)
```

```python
box = lambda text, w=90, h=44: pz.container(ui.label(text), center=True, width=w, height=h, bg=pz.theme.current().element, radius=6)
pz.container(pz.grid([box(str(i), w="fill") for i in range(1, 7)], columns=3, spacing=8, height=44), width=300)
```

```python
box = lambda text, w=90, h=44: pz.container(ui.label(text), center=True, width=w, height=h, bg=pz.theme.current().element, radius=6)
pz.container(pz.grid([box(str(i), w="fill") for i in range(1, 9)], columns=4, spacing=8, height=44), width=380)
```

### Tracks

```python
box = lambda text, w=90, h=44: pz.container(ui.label(text), center=True, width=w, height=h, bg=pz.theme.current().element, radius=6)
pz.container(pz.grid([box("100 px", w="fill"), box("1fr", w="fill")], columns=[100, "1fr"], spacing=8),
             width=340, height=44)
```

```python
box = lambda text, w=90, h=44: pz.container(ui.label(text), center=True, width=w, height=h, bg=pz.theme.current().element, radius=6)
pz.container(pz.grid([pz.cell(box("header", w="fill"), column=0, row=0, column_span=2),
                      pz.cell(box("a", w="fill"), column=0, row=1),
                      pz.cell(box("b", w="fill"), column=1, row=1)], columns=["1fr", "1fr"], spacing=8),
             width=300, height=96)
```

## Examples

### Tracks and spans

Numbers are pixels, `"1fr"` shares the free space and `"auto"` fits the content.

**Code:**

```python
box = lambda text, w=90, h=44: pz.container(ui.label(text), center=True, width=w, height=h, bg=pz.theme.current().element, radius=6)
pz.container(pz.grid([
    pz.cell(box("header", w="fill"), column=0, row=0, column_span=2),
    pz.cell(box("sidebar", w="fill", h="fill"), column=0, row=1),
    pz.cell(box("content", w="fill", h="fill"), column=1, row=1),
], columns=[120, "1fr"], rows=[44, 110], spacing=8), width=440)
```

## Events

Grid has no events of its own: it shows what you give it. Like every widget it also has the **18 common events** (`click`, `double_click`, `right_click`, `mouse_enter`, `drag`, `key_down`, `resize`…), attached with `.on(...)`: see [Events](https://albakore.github.io/pyzed/guides/events/) and [Events of every component](https://albakore.github.io/pyzed/library/events/).

## Properties and API

### `pz.grid`

```python
grid(
    children=None,
    *,
    columns=None,
    rows=None,
    max_width=None,
    spacing=0.0,
    row_spacing=None,
    height=None,
    aspect_ratio=None,
    width=None,
    padding=None,
    align_x=None,
    align_y=None,
)
```

Lays out its children in a grid. With `columns=3` the columns are equal (or `max_width` fits as many as possible). With track lists (`columns=[200, "1fr", "auto"]`, `rows=...`) it works like a CSS grid: numbers are pixels, `"auto"` fits the content and `"<n>fr"` shares the space left. Wrap children in `pz.cell` to place them and make them span; the rest fill the free cells row by row. See [Layout](https://albakore.github.io/pyzed/guides/layout/#grids).

| Property | Default | Description |
| --- | --- | --- |
| `children` | `None` | List of children. Nested lists are flattened and `None` and `False` are ignored, so you can write `cond and widget`. |
| `columns` | `None` | Number of equal columns, or tracks: a list (`[200, "1fr", "auto"]`) or a string (`"200 1fr auto"`). |
| `rows` | `None` | Row tracks, like `columns`. Rows beyond the list are `"auto"`. |
| `max_width` | `None` | Fits as many columns of at most this width as possible (`columns=<int>` only). |
| `spacing` | `0.0` | Space between cells. |
| `row_spacing` | `None` | Space between rows, if different. |
| `height` | `None` | With `columns=<int>`: height of each row. With tracks: the grid's height. |
| `aspect_ratio` | `None` | Keeps cells at this width/height ratio (`columns=<int>` only). |
| `width` | `None` | With `columns=<int>`: pixels. With tracks: the grid's width (default `"fill"`). |
| `padding` | `None` | Space around the cells. |
| `align_x` | `None` | Horizontal alignment of items in their cells: `"start"`, `"center"`, `"end"`. |
| `align_y` | `None` | Vertical alignment of items in their cells. |

[Full reference →](https://albakore.github.io/pyzed/reference/widgets/#grid)

### `pz.cell`

```python
cell(
    content,
    *,
    column=None,
    row=None,
    column_span=1,
    row_span=1,
    align_x=None,
    align_y=None,
)
```

Places a child in a track grid: its column and row (from 0) and how many it spans. Children without a cell fill the free cells row by row. Outside a grid it is just the child.

| Property | Default | Description |
| --- | --- | --- |
| `content` | *required* | The widget. |
| `column` | `None` | Column index (from 0). |
| `row` | `None` | Row index (from 0). |
| `column_span` | `1` | Columns it covers. |
| `row_span` | `1` | Rows it covers. |
| `align_x` | `None` | Horizontal alignment in the cell. |
| `align_y` | `None` | Vertical alignment in the cell. |

[Full reference →](https://albakore.github.io/pyzed/reference/widgets/#cell)

## Related

- [Flex](https://albakore.github.io/pyzed/library/flex/): CSS flexbox: justify, align, gap, wrap and grow.
- [Row](https://albakore.github.io/pyzed/library/row/): Lays out children horizontally.
- [Column](https://albakore.github.io/pyzed/library/column/): Stacks children vertically.
