W3docs

CSS grid-template-rows Property

Learn the CSS grid-template-rows property: track sizes, fr units, repeat(), minmax(), named lines, subgrid, and real-world examples.

The grid-template-rows property defines how many rows a CSS grid has and how tall each one is. You list the track sizes one after another, separated by spaces, and CSS creates one explicit row per value. So grid-template-rows: 100px 200px makes two rows — the first 100 px tall, the second 200 px tall.

This property only affects grid containers (elements with display: grid or display: inline-grid). It is the row-direction counterpart of grid-template-columns, and the two are often written together to lay out a full grid.

A track size can be a fixed length, a percentage, a flexible fr unit, a content-based keyword, or a function such as repeat() and minmax(). Mixing these is what makes grid layouts flexible:

  • Use a length (px, rem) when you want a row to stay an exact height.
  • Use fr when you want rows to share the leftover space proportionally.
  • Use auto or min-content / max-content when the row should grow to fit its content.
  • Use repeat() to avoid typing the same size many times.
  • Use minmax() when a row needs a floor and a ceiling (for example, "at least 100px, but grow if needed").
Info

Rows you create here are the explicit grid. If items overflow into rows you did not define, those extra rows are sized by grid-auto-rows instead.

Initial Valuenone
Applies toGrid containers.
InheritedNo.
AnimatableYes. The size of the rows is animatable.
VersionCSS Grid Layout Module Level 1
DOM Syntaxobject.style.gridTemplateRows = "20px 100px"

Syntax

grid-template-rows: none
                  | auto
                  | max-content
                  | min-content
                  | <length>
                  | <percentage>
                  | <flex>           /* e.g. 1fr */
                  | fit-content(<length-percentage>)
                  | repeat(<count>, <track-list>)
                  | minmax(<min>, <max>)
                  | subgrid
                  | [line-name] <track-size> [line-name];

The standard keywords initial and inherit also apply, as with every CSS property.

Basic usage

Auto-sized rows

With auto, each row grows to fit its tallest cell. This is the most common starting point.

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
    <style>
      .auto-container {
        display: grid;
        grid-template-columns: auto auto auto auto;
        grid-template-rows: auto auto;
        gap: 10px;
        background-color: #ccc;
        padding: 10px;
        margin-top: 30px;
      }
      .auto-container > div {
        background-color: #eee;
        text-align: center;
        padding: 30px 0;
        font-size: 30px;
      }
    </style>
  </head>
  <body>
    <h2>grid-template-rows: auto auto</h2>
    <div class="auto-container">
      <div>1</div>
      <div>2</div>
      <div>3</div>
      <div>4</div>
      <div>5</div>
      <div>6</div>
      <div>7</div>
      <div>8</div>
    </div>
  </body>
</html>
CSS grid-template-rows: auto auto example result

With grid-template-rows: auto auto, both rows grow to fit their content, so every cell is the same height as its tallest sibling in that row.

Fixed-height rows

Pass pixel values to pin rows to an exact height regardless of content.

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
    <style>
      .grid-container {
        display: grid;
        grid-template-columns: auto auto auto auto;
        grid-template-rows: 100px 300px;
        gap: 10px;
        background-color: #ccc;
        padding: 10px;
      }
      .grid-container > div {
        background-color: #eee;
        text-align: center;
        padding: 20px 0;
        font-size: 30px;
      }
    </style>
  </head>
  <body>
    <h2>grid-template-rows: 100px 300px</h2>
    <div class="grid-container">
      <div>1</div>
      <div>2</div>
      <div>3</div>
      <div>4</div>
      <div>5</div>
      <div>6</div>
      <div>7</div>
      <div>8</div>
    </div>
  </body>
</html>

Here the rows are fixed: the first is always 100 px tall and the second always 300 px, no matter how much content the cells hold. Content that overflows those heights is clipped or scrolls depending on the overflow setting.

fr units, repeat(), and minmax()

The fr unit

fr ("fraction") represents a share of the free space left in the grid after fixed-size tracks have been placed. Free space is the grid's total size minus the space taken by tracks with absolute or content-based sizes.

/* Three equal rows */
grid-template-rows: 1fr 1fr 1fr;

/* Header takes half, body takes the other half */
grid-template-rows: 1fr 1fr;

/* Header is fixed, body gets all remaining space */
grid-template-rows: 80px 1fr;

The fr unit is useful when the grid has a known height (set on the container) and you want tracks to fill it without doing any arithmetic.

repeat()

repeat(count, track-list) is shorthand for repeating one or more track sizes.

/* Same as: 1fr 1fr 1fr 1fr */
grid-template-rows: repeat(4, 1fr);

/* Alternating: 80px 1fr 80px 1fr */
grid-template-rows: repeat(2, 80px 1fr);

minmax()

minmax(min, max) gives a track a minimum and a maximum size. The browser resolves the actual size somewhere in that range depending on content and available space.

/* Row is at least 80px; grows with content up to 200px */
grid-template-rows: minmax(80px, 200px);

/* Row is at least 80px; grows to fill remaining space */
grid-template-rows: minmax(80px, 1fr);

Combining all three

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
    <style>
      .flex-grid {
        display: grid;
        height: 600px;
        grid-template-columns: 1fr 1fr;
        grid-template-rows: repeat(2, 1fr) minmax(80px, auto);
        gap: 10px;
        background-color: #ccc;
        padding: 10px;
      }
      .flex-grid > div {
        background-color: #eee;
        text-align: center;
        padding: 10px;
        font-size: 24px;
      }
    </style>
  </head>
  <body>
    <h2>fr, repeat() and minmax()</h2>
    <div class="flex-grid">
      <div>1</div>
      <div>2</div>
      <div>3</div>
      <div>4</div>
      <div>5</div>
      <div>6</div>
    </div>
  </body>
</html>

The grid is 600 px tall. repeat(2, 1fr) creates two rows that each take an equal share of the available height. The third row uses minmax(80px, auto): it is at least 80 px tall but expands if its content grows taller than that.

Named line tracks

You can give the lines between rows a name by wrapping the name in square brackets. Named lines make it much easier to position items with grid-row without counting grid lines.

.layout {
  display: grid;
  grid-template-rows:
    [header-start] 80px [header-end body-start]
    1fr
    [body-end footer-start] 60px [footer-end];
}

/* Place an item from body-start to body-end */
.main {
  grid-row: body-start / body-end;
}

A line can carry multiple names separated by spaces inside the same brackets — [header-end body-start] means the same line is the end of the header and the start of the body.

Content-based keywords

auto

auto means the track is sized by its content (equivalent to minmax(auto, auto)). The row grows to the tallest item it holds, but it will not shrink below the minimum content size. When fr tracks are also present in the same declaration, auto tracks are resolved first and the fr tracks share the remaining space.

min-content

The row is exactly tall enough to fit the smallest content in any of its cells — in practice, as tall as the longest word or smallest image.

max-content

The row is tall enough to fit the largest content without wrapping. Equivalent to giving every cell as much vertical space as it wants.

fit-content(<value>)

fit-content(200px) behaves like auto (grows with content) but caps out at the provided argument. Equivalent to min(max-content, max(auto, 200px)). Useful when you want a row to be content-sized but never grow beyond a limit.

subgrid

When a grid item is itself a grid container, subgrid on grid-template-rows tells that inner grid to use the parent grid's row tracks rather than creating its own. This lets you align content inside nested grid items with the outer grid's rhythm.

.parent {
  display: grid;
  grid-template-rows: 80px 1fr 60px;
}

.child {
  display: grid;
  /* This child spans 3 rows of the parent */
  grid-row: 1 / 4;
  /* Adopt those same 3 row tracks */
  grid-template-rows: subgrid;
}

subgrid has been widely supported since late 2023 (Chrome 117+, Firefox 71+, Safari 16+).

auto-fill and auto-fit in repeat()

auto-fill and auto-fit are used inside repeat() to create as many tracks as will fit the container. They are more commonly seen with grid-template-columns, but they work identically with rows when the container has a fixed height.

/* As many rows of at least 100px as will fit */
grid-template-rows: repeat(auto-fill, minmax(100px, 1fr));
  • auto-fill — fills the grid with as many tracks as possible, even if some are empty.
  • auto-fit — same as auto-fill, but collapses empty tracks to zero size so items stretch to fill available space.

Values

ValueDescription
noneDefault. No explicit rows are defined; all rows are implicit.
autoThe row height is determined by its content or available space.
max-contentThe row is as tall as the largest intrinsic size among its items.
min-contentThe row is as tall as the smallest intrinsic size among its items.
minmax(min, max)The track size is within the given range. min cannot be fr; max can be.
<length>A fixed height such as 100px or 2rem.
<percentage>A height relative to the grid container's height (must be definite).
<flex> (fr)A non-negative dimension that takes a share of the remaining free space.
fit-content(<value>)Content-sized but capped at the provided argument.
repeat(count, tracks)Repeats a pattern of track sizes. count can be a number, auto-fill, or auto-fit.
subgridThe track list is inherited from the parent grid.
initialResets the property to its default (none).
inheritInherits the value from the parent element.

Common gotchas

  • fr requires a definite container height. If the grid container has no explicit height, there is no free space for fr rows to share — they collapse to auto sizing instead. Always set a height (or min-height) on the container when using fr in rows.
  • Percentages require a definite container height for the same reason. If the container's height is intrinsic, percentage row sizes also resolve to auto.
  • Explicit rows only. This property sizes the rows you declare. Extra rows generated by overflow items are sized by grid-auto-rows — those implicit rows default to auto if grid-auto-rows is not set.
  • minmax(0, 1fr) vs 1fr. The fr unit has an implicit minimum of auto, so 1fr rows cannot shrink below their content size. Use minmax(0, 1fr) when you explicitly want rows to shrink below content — for example, inside scroll containers.

Practice

Practice
What does the grid-template-rows property in CSS do?
What does the grid-template-rows property in CSS do?
  • grid-template-columns — the column-direction counterpart of this property.
  • grid-auto-rows — sizes rows created implicitly, outside the explicit grid.
  • grid-template-areas — names grid areas to place items by reference.
  • grid-template — shorthand for rows, columns, and areas in one declaration.
  • grid-row — shorthand to place or span a grid item across row tracks.
  • grid-auto-flow — controls the direction and packing algorithm for auto-placed items.
  • grid — the full grid shorthand and a starting point for grid layout.
Was this page helpful?