# Part 4: CSS Grid

## Introduction

Flexbox handles one dimension at a time — a row or a column. CSS Grid handles two dimensions simultaneously — rows and columns together. For page-level layouts and anything that needs items aligned in both directions at once, Grid is the right tool.

I use Grid mainly for page structure (header, sidebar, main, footer arranged in a two-dimensional space) and for uniform card grids where items should align across both rows and columns. This part covers every Grid property I use and the patterns that come up most often.

***

## The Grid Mental Model

Grid works on two elements: a **grid container** and its direct **grid items**.

```html
<div class="grid">      <!-- grid container -->
  <div>Item 1</div>
  <div>Item 2</div>
  <div>Item 3</div>
  <div>Item 4</div>
</div>
```

```css
.grid {
  display: grid;
}
```

The container defines the track structure (columns and rows). Items are placed into cells formed by the intersection of tracks.

***

## Defining Columns and Rows

### `grid-template-columns`

```css
.grid {
  /* Three equal columns */
  grid-template-columns: 200px 200px 200px;

  /* Two columns: one fixed, one flexible */
  grid-template-columns: 240px 1fr;

  /* Three equal flexible columns */
  grid-template-columns: 1fr 1fr 1fr;

  /* Shorthand with repeat() */
  grid-template-columns: repeat(3, 1fr);

  /* Named sizes */
  grid-template-columns: repeat(12, 1fr);   /* 12-column grid */
}
```

### `grid-template-rows`

```css
.grid {
  grid-template-rows: auto auto;        /* rows size to content */
  grid-template-rows: 60px 1fr 40px;   /* fixed header, flexible content, fixed footer */
}
```

### The `fr` Unit

`fr` stands for "fraction of available space". It distributes remaining space after fixed-size tracks are accounted for.

```css
/* 1 fixed column, 2 equal flexible columns */
grid-template-columns: 240px 1fr 1fr;
/* → 240px sidebar, remaining space split equally */

/* Ratio 1:2:1 */
grid-template-columns: 1fr 2fr 1fr;
/* → middle column gets twice the space of outer columns */
```

***

## The `repeat()` Function

```css
/* Explicit repetition */
grid-template-columns: repeat(4, 1fr);        /* 4 equal columns */
grid-template-columns: repeat(3, 200px 1fr);  /* pattern repeated 3 times */

/* Auto-fill: create as many columns as fit */
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));

/* Auto-fit: same as auto-fill but collapses empty tracks */
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
```

### `auto-fill` vs `auto-fit`

Both fill the container with as many columns as will fit at the minimum size. The difference is visible when items do not fill the last row:

* `auto-fill` — empty columns are created and take space
* `auto-fit` — empty columns collapse to 0, items expand to fill

For card grids, `auto-fit` is usually what I want.

***

## The `minmax()` Function

Defines a size range for a track: `minmax(minimum, maximum)`.

```css
/* Column is at least 250px but grows up to 1fr */
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
```

This single line creates a fully responsive grid: many columns on wide screens, fewer on narrow, no media query needed.

```css
/* Row is at least content height but can grow to 150px max */
grid-template-rows: repeat(3, minmax(auto, 150px));
```

***

## `gap`

```css
.grid {
  gap: 1.5rem;            /* same for rows and columns */
  gap: 1rem 2rem;         /* row-gap column-gap */
  row-gap: 1rem;
  column-gap: 2rem;
}
```

***

## Named Template Areas

`grid-template-areas` allows placing items by name rather than by line numbers — ideal for page-level layouts because the layout is visible in the CSS itself.

```css
.page {
  display: grid;
  grid-template-columns: 240px 1fr;
  grid-template-rows: 60px 1fr 40px;
  grid-template-areas:
    "header  header"
    "sidebar main"
    "footer  footer";
  min-height: 100vh;
}

.page-header  { grid-area: header; }
.page-sidebar { grid-area: sidebar; }
.page-main    { grid-area: main; }
.page-footer  { grid-area: footer; }
```

```html
<div class="page">
  <header class="page-header">Header</header>
  <aside  class="page-sidebar">Sidebar</aside>
  <main   class="page-main">Content</main>
  <footer class="page-footer">Footer</footer>
</div>
```

Use `.` for empty cells:

```css
grid-template-areas:
  "header header"
  ".      main"
  "footer footer";
```

***

## Placing Items with Line Numbers

Grid lines are numbered starting from 1. Items can span across lines using `grid-column` and `grid-row`.

```
Column lines:  1    2    3    4
               |    |    |    |
Row lines: 1 — +----+----+----+
               |    |    |    |
           2 — +----+----+----+
               |    |    |    |
           3 — +----+----+----+
```

```css
.item {
  grid-column: 1 / 3;   /* from column line 1 to line 3 (spans 2 columns) */
  grid-row: 1 / 2;      /* first row */
}

/* Span keyword */
.item {
  grid-column: 1 / span 2;   /* start at line 1, span 2 columns */
  grid-row: span 2;           /* span 2 rows from current position */
}

/* Negative lines count from the end */
.full-width {
  grid-column: 1 / -1;   /* from first to last column line */
}
```

***

## Implicit Grid

When items are placed outside the explicitly defined tracks, the browser creates **implicit** tracks automatically.

```css
.grid {
  grid-template-columns: repeat(3, 1fr);
  /* row height is implicit — auto by default */

  /* Control implicit row size */
  grid-auto-rows: minmax(100px, auto);

  /* Control implicit column size (for auto-placed columns) */
  grid-auto-columns: 1fr;
}
```

### `grid-auto-flow`

Controls how auto-placed items fill the grid.

```css
.grid {
  grid-auto-flow: row;     /* default: fills row by row */
  grid-auto-flow: column;  /* fills column by column */
  grid-auto-flow: dense;   /* fills gaps with smaller items (visual reorder) */
}
```

`dense` is useful for masonry-like layouts where items have varying row spans and you want to fill holes.

***

## Alignment in Grid

Grid has full alignment control in both dimensions.

### Container-level (aligns all items)

```css
.grid {
  /* Along column axis (inline/horizontal) */
  justify-items: start | end | center | stretch;   /* default: stretch */

  /* Along row axis (block/vertical) */
  align-items: start | end | center | stretch;     /* default: stretch */

  /* Both axes */
  place-items: center;           /* align-items / justify-items */
  place-items: start center;
}
```

### Distributing the grid tracks within the container

```css
.grid {
  /* When total grid is smaller than container */
  justify-content: start | end | center | space-between | space-around | space-evenly;
  align-content: start | end | center | space-between | space-around | space-evenly;
}
```

### Item-level overrides

```css
.item {
  justify-self: start | end | center | stretch;
  align-self: start | end | center | stretch;
  place-self: center;
}
```

***

## Naming Grid Lines

Grid lines can be named for more readable placement:

```css
.grid {
  grid-template-columns:
    [content-start] 1fr [content-end sidebar-start] 240px [sidebar-end];
}

.main {
  grid-column: content-start / content-end;
}

.sidebar {
  grid-column: sidebar-start / sidebar-end;
}
```

***

## Common Grid Patterns

### Responsive Card Grid (No Media Query)

```css
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 1.5rem;
}
```

Cards reflow automatically: 3 columns on wide screens, 2 on medium, 1 on mobile.

### Holy Grail Layout

```css
.page {
  display: grid;
  grid-template:
    "header"  60px
    "main"    1fr
    "footer"  40px
    / 1fr;
  min-height: 100vh;
}

@media (min-width: 768px) {
  .page {
    grid-template:
      "header  header"  60px
      "sidebar main"    1fr
      "footer  footer"  40px
      / 240px 1fr;
  }
}

header  { grid-area: header; }
aside   { grid-area: sidebar; }
main    { grid-area: main; }
footer  { grid-area: footer; }
```

Mobile-first: single column. Wider screens: sidebar + content.

### Dashboard Grid

```css
.dashboard {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 1rem;
}

.stat-card    { grid-column: span 3; }   /* 4 per row on 12-col grid */
.main-chart   { grid-column: span 8; }
.side-panel   { grid-column: span 4; }
.full-table   { grid-column: span 12; }
```

### Centring with Grid

```css
.centred {
  display: grid;
  place-items: center;
  min-height: 100vh;
}
```

***

## Flexbox vs Grid — When to Use Each

I decide based on the layout direction:

| Use case                                              | Tool    |
| ----------------------------------------------------- | ------- |
| Items in one row/column (nav bar, button group)       | Flexbox |
| Content-first sizing (items define track sizes)       | Flexbox |
| Two-dimensional alignment (rows and columns together) | Grid    |
| Layout-first design (define tracks then fill them)    | Grid    |
| Responsive card grid without media queries            | Grid    |
| Page-level layout (header, sidebar, main, footer)     | Grid    |

In practice, I often use both: Grid for the page structure and Flexbox inside components.

***

## Summary

| Property                   | Purpose                       |
| -------------------------- | ----------------------------- |
| `display: grid`            | Activates grid layout         |
| `grid-template-columns`    | Define column tracks          |
| `grid-template-rows`       | Define row tracks             |
| `fr` unit                  | Fraction of available space   |
| `repeat(n, size)`          | Repeat track definitions      |
| `auto-fit` / `auto-fill`   | Create as many columns as fit |
| `minmax(min, max)`         | Track size range              |
| `gap`                      | Space between tracks          |
| `grid-template-areas`      | Name-based area placement     |
| `grid-column` / `grid-row` | Place items on specific lines |
| `grid-auto-rows`           | Implicit track sizing         |
| `grid-auto-flow: dense`    | Fill gaps with smaller items  |
| `place-items: center`      | Centre all items in both axes |
| `place-self: center`       | Centre a single item          |
| `grid-column: 1 / -1`      | Span full width               |

***

## Up Next

[Part 5](https://blog.htunnthuthu.com/getting-started/programming/css-101/css-101-part-5) covers CSS custom properties, responsive design with media queries, and modern CSS features.
