# Grid
> A primitive for creating fluid, nestable grid layouts.

## Import

```js
import { Grid, GridItem } from '@gemini-suite/vera-react';
```

- `Grid`: The main grid wrapper defining the shape of the grid.
- `GridItem`: Used as a child of `Grid` to control the span and start positions within the grid.

## Background

**Grid** creates organized and consistent layouts, by providing a standard for positioning elements.
Within a `Grid` container, `GridItem`s can be placed and aligned along a series of columns and rows via specific props.

The **Grid** defaults to 12 columns scale, but you can manually adapt to different breakpoints by setting number of columns specific to each breakpoint.
Pretty much all of the props available on `Grid` and `GridItem` are responsive, meaning they accept either a single value or an object that maps values to [breakpoints defined in Vera](/tokens/breakpoints).
The consumer of the component is in control over how elements are laid out on the grid under different conditions, which offers huge flexibility.

<Callout variant="tip">

[See Breakpoints page](/tokens/breakpoints) to get an overview of the available breakpoints in Vera.

</Callout>

**Grid** is an abstraction over [CSS Grid Layout Module](https://www.w3.org/TR/2020/CRD-css-grid-1-20201218/).

<Grid
  columns={{
    '@initial': '1',
    '@mqLargeAndUp': '2'
  }}
  columnGap="spacingL"
  className="mTm"
>
  <GridItem>
    <Card
      href="https://web.dev/learn/css/grid"
      title="Learn more about CSS Grid Layout"
      actionIcon="externalLink"
    />
  </GridItem>
</Grid>

## Examples

### Default configuration

Place items in a grid container and each cell will align to a column. By default each column will have an equal share of space available in the grid container and you can have up to 12 columns. Any cells that do not fit on a single row will wrap to a new row.
The grid adds new rows as it grows and there is no limit.

```jsx
<Grid>
  {Array.from(Array(24)).map((_, i) => (
    <GridItem key={i}>
      <ExampleBox>{i + 1}</ExampleBox>
    </GridItem>
  ))}
</Grid>
```

### Customizing columns

Large column count comes in handy when you want some finer control of things inside the grid,
but for simple layouts you may want to customize the number of columns.

```jsx
<Grid columns="2">
  <GridItem>
    <ExampleBox />
  </GridItem>
  <GridItem>
    <ExampleBox />
  </GridItem>
</Grid>
```

#### Responsive

At different breakpoints, you may want different column counts. The `columns` prop is responsive.
For example, if you wanted a single column on mobile and three columns from larger screens upwards:

```jsx
<Grid
  columns={{
    '@initial': '1',
    '@mqLargeAndUp': '3'
  }}
>
  <GridItem>
    <ExampleBox />
  </GridItem>
  <GridItem>
    <ExampleBox />
  </GridItem>
  <GridItem>
    <ExampleBox />
  </GridItem>
</Grid>
```

### Specifying the rows

By default there are no explicit rows; instead rows are auto-generated as items are added.
There are however some cases where you do want to be specific about the number of rows. Grid component supports up to 6 explicit rows.

In the example below the flow of the grid items is set to `column`, as opposed to the default `row`.
Grid's `rows` are explicitly defined and `columns` are set to `none` to declare no explicit columns. This results in grid items flowing down column by column, adding new columns if needed.

```jsx
<Grid rows="3" columns="none" flow="column">
  {Array.from(Array(9)).map((_, i) => (
    <GridItem key={i}>
      <ExampleBox>{i + 1}</ExampleBox>
    </GridItem>
  ))}
</Grid>
```

### Spanning columns/rows

In some layouts, you may need certain grid items to span specific amount of columns and rows instead of an even distribution.

#### Columns

Pass the `colSpan` prop to the `GridItem` component to span across columns.

```jsx
<Grid columns="6" rows="2">
  <GridItem rowSpan="2" colSpan="2">
    <ExampleBox css={{ height: '100%' }}>1</ExampleBox>
  </GridItem>
  <GridItem colSpan="2">
    <ExampleBox>2</ExampleBox>
  </GridItem>
  <GridItem colSpan="2">
    <ExampleBox>3</ExampleBox>
  </GridItem>
  <GridItem colSpan="4">
    <ExampleBox>4</ExampleBox>
  </GridItem>
</Grid>
```

#### Rows

Pass the `rowSpan` prop to the `GridItem` component to span across rows.

```jsx
<Grid rows="3" columns="none" flow="column" autoColumns="fr">
  <GridItem rowSpan="2">
    <ExampleBox css={{ height: '100%' }}>1</ExampleBox>
  </GridItem>
  <GridItem>
    <ExampleBox>2</ExampleBox>
  </GridItem>
  <GridItem colSpan="2">
    <ExampleBox>3</ExampleBox>
  </GridItem>
  <GridItem colSpan="2">
    <ExampleBox>4</ExampleBox>
  </GridItem>
  <GridItem colSpan="2">
    <ExampleBox>5</ExampleBox>
  </GridItem>
</Grid>
```

#### Responsive

Props for controlling spanning are responsive. You can specify how many grid columns an item should stretch across per breakpoint.

```jsx
<Grid
  columns={{
    '@initial': '1',
    '@mqLargeAndUp': '3'
  }}
>
  <GridItem>
    <ExampleBox />
  </GridItem>
  <GridItem>
    <ExampleBox />
  </GridItem>
  <GridItem>
    <ExampleBox />
  </GridItem>
  <GridItem>
    <ExampleBox />
  </GridItem>
  <GridItem
    colSpan={{
      '@initial': 'auto',
      '@mqLargeAndUp': '2'
    }}
  >
    <ExampleBox />
  </GridItem>
  <GridItem
    colSpan={{
      '@initial': 'auto',
      '@mqLargeAndUp': 'full'
    }}
  >
    <ExampleBox />
  </GridItem>
</Grid>
```

### Starting and ending lines

Items in the grid can be instructed to start or end at the _nth_ grid line.

<Callout variant="tip">
  Note that CSS grid lines start at 1, not 0, so a full-width item in a 6-column
  grid would start at line 1 and end at line 7.
</Callout>

#### Column axis

To position grid items along the horizontal column axis, `colStart` and `colEnd` properties.
These can also be combined with the `colSpan` prop to span a specific number of columns.

```jsx
<Grid columns="6">
  <GridItem>
    <ExampleBox striped />
  </GridItem>
  <GridItem colStart="2" colSpan="4">
    <ExampleBox />
  </GridItem>
  <GridItem>
    <ExampleBox striped />
  </GridItem>
  <GridItem colStart="1" colEnd="3">
    <ExampleBox />
  </GridItem>
  <GridItem>
    <ExampleBox striped />
  </GridItem>
  <GridItem>
    <ExampleBox striped />
  </GridItem>
  <GridItem colEnd="7" colSpan="2">
    <ExampleBox />
  </GridItem>
  <GridItem colStart="1" colEnd="7">
    <ExampleBox />
  </GridItem>
</Grid>
```

#### Row axis

To position grid items along the row axis, use `rowStart` and `rowEnd` props. These can also be combined with the `rowSpan` prop to span a specific number of rows.

```jsx
<Grid flow="column" columns="none" rows="3" autoColumns="fr">
  <GridItem rowSpan="2" rowStart="2">
    <ExampleBox css={{ height: '100%' }} />
  </GridItem>
  <GridItem>
    <ExampleBox striped />
  </GridItem>
  <GridItem>
    <ExampleBox striped />
  </GridItem>
  <GridItem>
    <ExampleBox striped />
  </GridItem>
  <GridItem rowStart="1" rowEnd="4">
    <ExampleBox css={{ height: '100%' }} />
  </GridItem>
</Grid>
```

#### Responsive

If you need to customize the placement of an item at a specific breakpoint, the `GridItem` props are responsive.

```jsx
<Grid
  columns={{
    '@initial': '3',
    '@mqLargeAndUp': '5'
  }}
>
  <GridItem>
    <ExampleBox />
  </GridItem>
  <GridItem
    colStart={{
      '@initial': 'auto',
      '@mqLargeAndUp': '3'
    }}
    rowStart={{
      '@initial': 'auto',
      '@mqLargeAndUp': '2'
    }}
  >
    <ExampleBox />
  </GridItem>
  <GridItem
    colStart={{
      '@initial': 'auto',
      '@mqLargeAndUp': '5'
    }}
    rowStart={{
      '@initial': 'auto',
      '@mqLargeAndUp': '3'
    }}
  >
    <ExampleBox />
  </GridItem>
</Grid>
```

In the example below sidebar is positioned specifically, giving it a different visual order to the source code.

```jsx
<Grid
  columns={{
    '@initial': '1',
    '@mqLargeAndUp': '3'
  }}
>
  <GridItem
    colSpan={{
      '@initial': 'auto',
      '@mqLargeAndUp': '2'
    }}
  >
    <ExampleBox>Main content</ExampleBox>
  </GridItem>
  <GridItem
    rowStart={{
      '@initial': 'auto',
      '@mqLargeAndUp': '1'
    }}
    colStart="1"
  >
    <ExampleBox>Sidebar</ExampleBox>
  </GridItem>
</Grid>
```

### White space

#### Uniform gap size

Use `gap` property to change the white space between both rows and columns in a grid layout using [Vera's standard white space scale](/tokens/white-space).

<Callout variant="tip">

When no explicit `gap` is provided, the white space between the items defaults to `spacingM`.

</Callout>

```jsx
<Grid columns="3" gap="spacingXl">
  <GridItem>
    <ExampleBox />
  </GridItem>
  <GridItem>
    <ExampleBox />
  </GridItem>
  <GridItem>
    <ExampleBox />
  </GridItem>
</Grid>
```

#### Customizing row and column gaps independently

Use `rowGap` and `columnGap` to change the gap between rows and columns independently.

```jsx
<Grid columns="3" columnGap="spacingXl" rowGap="spacingM">
  {Array.from(Array(6)).map((_, i) => (
    <GridItem key={i}>
      <ExampleBox />
    </GridItem>
  ))}
</Grid>
```

#### Gapless

In case you want to remove the gaps altogether, set the `gap` prop to `none`.

```jsx
<Grid columns="3" gap="none">
  <GridItem>
    <ExampleBox />
  </GridItem>
  <GridItem>
    <ExampleBox />
  </GridItem>
  <GridItem>
    <ExampleBox />
  </GridItem>
</Grid>
```

### Sizing in the implicit grid

If there are more grid items than cells in the grid or when a grid item is positioned outside of the explicit grid (defined by `columns` or `rows`),
the grid container automatically generates implicit grid tracks by adding new grid lines.
The default for tracks in the implicit grid is for them to be auto-sized, meaning they will expand to contain the content you place into them.

#### Sizing implicit rows

Use `gridAutoRows` prop to define sizing of implicitly-created grid rows. In the example below all rows have the same size (the tallest item in the grid sets the height for all rows).

```jsx
<Grid columns="2" autoRows="fr" alignItems="end">
  <GridItem>
    <ExampleBox css={{ height: '5rem' }} />
  </GridItem>
  <GridItem>
    <ExampleBox />
  </GridItem>
  <GridItem>
    <ExampleBox />
  </GridItem>
  <GridItem align="start">
    <ExampleBox />
  </GridItem>
</Grid>
```

#### Sizing implicit columns

Use `gridAutoColumns` prop to define sizing of implicitly-created grid columns. In the example below `flow` is changed to `column` and each columns size is as small as possible without causing the content to overflow.

```jsx
<Grid columns="none" flow="column" autoColumns="min">
  <GridItem>
    <ExampleBox>
      <FakeText words="5,10" />
    </ExampleBox>
  </GridItem>
  <GridItem>
    <ExampleBox />
  </GridItem>
</Grid>
```

### Alignment options

#### Grid items alignment

`justifyItems` property defines the alignment of grid items along the inline (row) axis. In the example below we are aligning grid items to be flush with the start edge of their cell (by default they would have been stretched to fill it).

```jsx
<Grid
  columns="3"
  justifyItems="start"
  css={{
    backgroundColor: '$colorBlue10'
  }}
>
  <GridItem>
    <ExampleBox />
  </GridItem>
  <GridItem>
    <ExampleBox />
  </GridItem>
  <GridItem>
    <ExampleBox />
  </GridItem>
</Grid>
```

`alignItems` property defines the alignment of grid items along the block (column) axis.
In the example below grid items of varying height have been centered vertically.

```jsx
<Grid
  columns="3"
  alignItems="center"
  css={{
    backgroundColor: '$colorBlue10'
  }}
>
  <GridItem>
    <ExampleBox css={{ height: '6rem' }} />
  </GridItem>
  <GridItem>
    <ExampleBox />
  </GridItem>
  <GridItem>
    <ExampleBox css={{ height: '4.5rem' }} />
  </GridItem>
</Grid>
```

#### Grid alignment

Sometimes the total size of your grid might be less than the size of its grid container.
In this case you can set the alignment of the grid within the grid container.

`justifyContent` property defines the alignment of the grid along the inline (row) axis.

```jsx
<Grid
  columns="none"
  flow="column"
  justifyContent="end"
  css={{
    backgroundColor: '$colorBlue10'
  }}
>
  <GridItem>
    <ExampleBox />
  </GridItem>
  <GridItem>
    <ExampleBox />
  </GridItem>
  <GridItem>
    <ExampleBox />
  </GridItem>
</Grid>
```

`alignContent` property defines the alignment of the grid along the block (column) axis.

```jsx
<Grid
  columns="3"
  alignContent="end"
  css={{
    height: '6rem',
    backgroundColor: '$colorBlue10'
  }}
>
  <GridItem>
    <ExampleBox />
  </GridItem>
  <GridItem>
    <ExampleBox />
  </GridItem>
  <GridItem>
    <ExampleBox />
  </GridItem>
</Grid>
```

#### Individual grid items alignment

Alignment values can be set on individual grid items. `GridItem` exposes `align` and `justify` properties to provide granular control over the alignment of a single item inside the grid.
In the example below grid items are aligned to the end edge of their columns, except the middle one which is instructed to be placed in the center.

```jsx
<Grid
  columns="3"
  css={{
    backgroundColor: '$colorBlue10'
  }}
  alignItems="end"
>
  <GridItem>
    <ExampleBox striped css={{ height: '6rem ' }} />
  </GridItem>
  <GridItem align="center" justify="center">
    <ExampleBox />
  </GridItem>
  <GridItem>
    <ExampleBox striped />
  </GridItem>
</Grid>
```

### Nesting

Let's look at a common use case where we need to layout a view with a sidebar and a grid within the content area.

```jsx
<Grid
  columns={{
    '@initial': '1',
    '@mqLargeAndUp': '3'
  }}
  gap="none"
  css={{
    border: '1px solid $borderNeutralModerate',
    borderRadius: '$m',
    overflow: 'hidden'
  }}
>
  <GridItem>
    <Flex
      flow="column"
      main="space-between"
      css={{
        height: '100%',
        backgroundColor: '$backgroundNeutralModerate',
        padding: '$spacingM'
      }}
    >
      <Flex flow="column" gap="spacingS">
        <h3>Contact us</h3>
        <Box as="p" css={{ color: '$foregroundNeutralModerate', margin: 0 }}>
          We can't wait to hear from you. Feel free to get in touch with us.
        </Box>
      </Flex>
      <Box as="p" css={{ color: '$foregroundNeutralModerate', margin: 0 }}>
        Happy ST
        <br />
        000-111-222
      </Box>
    </Flex>
  </GridItem>
  <GridItem
    colSpan={{
      '@initial': 'auto',
      '@mqLargeAndUp': '2'
    }}
  >
    <Box css={{ padding: '$spacingM $spacingL' }}>
      <Grid
        columns={{
          '@initial': '1',
          '@mqMediumAndUp': '2'
        }}
        columnGap="spacingL"
        rowGap="spacingM"
      >
        <GridItem>
          <FormField.Root as={Flex} flow="column">
            <FormField.Label>First name</FormField.Label>
            <TextInput />
          </FormField.Root>
        </GridItem>
        <GridItem>
          <FormField.Root as={Flex} flow="column">
            <FormField.Label>Last name</FormField.Label>
            <TextInput />
          </FormField.Root>
        </GridItem>
        <GridItem>
          <FormField.Root as={Flex} flow="column">
            <FormField.Label>Email Address</FormField.Label>
            <TextInput />
          </FormField.Root>
        </GridItem>
        <GridItem>
          <FormField.Root as={Flex} flow="column">
            <FormField.Label>Topic</FormField.Label>
            <TextInput />
          </FormField.Root>
        </GridItem>
        <GridItem colSpan="full">
          <FormField.Root as={Flex} flow="column">
            <FormField.Label>Write your message</FormField.Label>
            <Textarea />
          </FormField.Root>
        </GridItem>
        <GridItem colSpan="full">
          <Button>Send message</Button>
        </GridItem>
      </Grid>
    </Box>
  </GridItem>
</Grid>
```

---

## API Reference

### Grid

| Name             | Type                                                                                            | Default      | Description                                                                                                                                                                                                                                                                                  | Required |
| ---------------- | ----------------------------------------------------------------------------------------------- | ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `as`             | `keyof JSX.IntrinsicElements \| React.ComponentType<any>`                                       | `div`        | Change the component to a different HTML tag or custom component. This will merge the original component props with the props of the supplied element/component and change the underlying DOM node.   For more details, read our [Composition](/get-started/composition#polymorphism) guide. |          |
| `css`            | `StitchesCss`                                                                                   |              | Apply styles directly to a component in a similar way how you would define inline styles. Vera uses [Stitches](https://stitches.dev/) under the hood with a fully-typed API and support for features like tokens, media queries or variants.                                                 |          |
| `display`        | `"grid" \| "inline-grid"`                                                                       | `"grid"`     | Set block or inline display of the grid container.                                                                                                                                                                                                                                           |          |
| `flow`           | `"row" \| "column" \| "dense" \| "row dense" \| "column dense"`                                 | `"row"`      | Control how the auto-placement algorithm works.                                                                                                                                                                                                                                              |          |
| `columns`        | `"none" \| "1" \| "2" \| "3" \| "4" \| "5" \| "6" \| "7" \| "8" \| "9" \| "10" \| "11" \| "12"` | `"12"`       | Defines the amount of explicit grid columns.                                                                                                                                                                                                                                                 |          |
| `rows`           | `"none" \| "1" \| "2" \| "3" \| "4" \| "5" \| "6"`                                              | `"none"`     | Defines the amount of explicit grid rows.                                                                                                                                                                                                                                                    |          |
| `autoColumns`    | `"auto" \| "min" \| "max" \| "fr"`                                                              | `"auto"`     | Specifies the size of implicitly-created grid columns.                                                                                                                                                                                                                                       |          |
| `autoRows`       | `"auto" \| "min" \| "max" \| "fr"`                                                              | `"auto"`     | Specifies the size of implicitly-created grid rows.                                                                                                                                                                                                                                          |          |
| `justifyItems`   | `"start" \| "center" \| "end" \| "stretch"`                                                     |              | Defines the alignment of the items inside the grid container on the inline (row) axis.                                                                                                                                                                                                       |          |
| `alignItems`     | `"start" \| "center" \| "end" \| "baseline" \| "stretch"`                                       |              | Defines the alignment of the items inside the grid container on the block (column) axis.                                                                                                                                                                                                     |          |
| `justifyContent` | `"start" \| "center" \| "end" \| "stretch" \| "space-between" \| "space-around"`                |              | Defines the alignment of the grid along the inline (row) axis.                                                                                                                                                                                                                               |          |
| `alignContent`   | `"start" \| "center" \| "end" \| "stretch" \| "space-between" \| "space-around"`                |              | Defines the alignment of the grid along the block (column) axis.                                                                                                                                                                                                                             |          |
| `gap`            | `SpacingToken`                                                                                  | `"spacingM"` | Spacing between both grid rows and columns.                                                                                                                                                                                                                                                  |          |
| `rowGap`         | `SpacingToken`                                                                                  |              | Spacing between grid rows.                                                                                                                                                                                                                                                                   |          |
| `columnGap`      | `SpacingToken`                                                                                  |              | Spacing between grid columns.                                                                                                                                                                                                                                                                |          |

### GridItem

| Name       | Type                                                                                                                 | Default | Description                                                                                                                                                                                                                                                                                  | Required |
| ---------- | -------------------------------------------------------------------------------------------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `as`       | `keyof JSX.IntrinsicElements \| React.ComponentType<any>`                                                            | `div`   | Change the component to a different HTML tag or custom component. This will merge the original component props with the props of the supplied element/component and change the underlying DOM node.   For more details, read our [Composition](/get-started/composition#polymorphism) guide. |          |
| `css`      | `StitchesCss`                                                                                                        |         | Apply styles directly to a component in a similar way how you would define inline styles. Vera uses [Stitches](https://stitches.dev/) under the hood with a fully-typed API and support for features like tokens, media queries or variants.                                                 |          |
| `colSpan`  | `"auto" \| "full" \| "1" \| "2" \| "3" \| "4" \| "5" \| "6" \| "7" \| "8" \| "9" \| "10" \| "11" \| "12"`            |         | The number of columns the grid item should span.                                                                                                                                                                                                                                             |          |
| `colStart` | `"auto" \| "1" \| "2" \| "3" \| "4" \| "5" \| "6" \| "7" \| "8" \| "9" \| "10" \| "11" \| "12" \| "13"`              |         | The column line number at which the grid item should start.                                                                                                                                                                                                                                  |          |
| `colEnd`   | `"auto" \| "1" \| "2" \| "3" \| "4" \| "5" \| "6" \| "7" \| "8" \| "9" \| "10" \| "11" \| "12" \| "13"`              |         | The column line number at which the grid item should end.                                                                                                                                                                                                                                    |          |
| `rowSpan`  | `"auto" \| "full" \| "1" \| "2" \| "3" \| "4" \| "5" \| "6"`                                                         |         | The number of rows the grid item should span.                                                                                                                                                                                                                                                |          |
| `rowStart` | `"auto" \| "1" \| "2" \| "3" \| "4" \| "5" \| "6" \| "7"`                                                            |         | The row line number at which the grid item should start.                                                                                                                                                                                                                                     |          |
| `rowEnd`   | `"auto" \| "1" \| "2" \| "3" \| "4" \| "5" \| "6" \| "7"`                                                            |         | The row line number at which the grid item should end.                                                                                                                                                                                                                                       |          |
| `justify`  | `"auto" \| "start" \| "center" \| "end" \| "stretch"`                                                                |         | Override default (or the one specified by `justifyItems` property on `Grid`) alignment along the inline (row) axis for the individual grid item.                                                                                                                                             |          |
| `align`    | `"auto" \| "start" \| "center" \| "end" \| "baseline" \| "stretch"`                                                  |         | Override default (or the one specified by `alignItems` property on `Grid`) alignment along the block (column) axis for the individual grid item.                                                                                                                                             |          |
| `order`    | `"first" \| "last" \| "none" \| "1" \| "2" \| "3" \| "4" \| "5" \| "6" \| "7" \| "8" \| "9" \| "10" \| "11" \| "12"` |         | Control the order in which `GridItem` appears in the `Grid` container.                                                                                                                                                                                                                       |          |
