Show API reference for

Insert a responsive grid container.

Inserts a grid for repeated cards, metric walls, galleries, and dashboard panels. Direct children become cells and reflow with the available width. Use st.columns for a known side-by-side split and st.container(horizontal=True) for natural-width toolbars.

To add elements to the returned container, use the with notation (preferred) or call commands on the returned object. Group multiple elements or span tracks with grid.cell().

st.empty() as a direct child reserves a cell. Later writes replace that cell and do not insert a new one. A heading inside the grid also takes a cell, so keep section headings outside the grid.

Function signature[source]

st.grid(columns="auto", *, min_column_width="auto", wrap=True, gap="small", vertical_alignment="top", border=False, row_height="content", width="stretch", height="content", key=None, dense=False)

Parameters

columns ("auto" or int)

Number of equal-width columns. This can be one of the following:

  • "auto" (default): Fit as many columns as the container allows, using min_column_width. Automatic layouts are also capped at 24 columns.
  • An integer from 1 to 24: Maximum column count. With wrap=True (default), the grid wraps to fewer columns when cells would fall below min_column_width. With wrap=False, this count is kept at every width. For example, st.grid(4) shows three columns on the default centered layout because four would be narrower than min_column_width.

min_column_width ("auto" or int)

The minimum width of each column before the grid wraps to fewer columns. This can be one of the following:

  • "auto" (default): A theme-based width of about 200 pixels.
  • An integer: A width in pixels.

Cell border and padding sit inside this width. With wrap=True, the grid drops a column before cells would be narrower than this width; once one column remains, it uses the container width and may be narrower. With wrap=False, cells shrink to this width and the grid then scrolls horizontally.

wrap (bool)

Whether the number of columns can decrease as the container gets narrower. This can be one of the following:

  • True (default): The grid uses fewer columns when cells would become narrower than min_column_width.
  • False: The grid keeps the declared number of columns and scrolls horizontally instead.

Setting wrap=False with columns="auto" raises an exception, because there is no declared column count to keep.

gap ("xxsmall", "xsmall", "small", "medium", "large", "xlarge", "xxlarge", int, tuple, list, or None)

The size of the gap between cells. Pass one value to use the same gap between rows and columns, or a 2-tuple or 2-list (row_gap, column_gap) to set them separately. Each value can be one of the following:

  • "xxsmall": 0.25rem gap between the cells.
  • "xsmall": 0.5rem gap between the cells.
  • "small" (default): 1rem gap between the cells.
  • "medium": 2rem gap between the cells.
  • "large": 4rem gap between the cells.
  • "xlarge": 6rem gap between the cells.
  • "xxlarge": 8rem gap between the cells.
  • A non-negative integer specifying the gap in pixels. For example, gap=20 sets a 20-pixel gap.
  • None: No gap between the cells.

The rem unit is relative to the theme.baseFontSize configuration option.

vertical_alignment ("top", "center", or "bottom")

Vertical alignment of content inside the cell. The cell frame still fills the row. This can be one of the following:

  • "top" (default): Align content to the top of the cell.
  • "center": Center content vertically in the cell.
  • "bottom": Align content to the bottom of the cell.

border (bool)

Whether to show a border around each cell. If this is False (default), no border is shown. If this is True, a border is shown around each cell.

row_height ("content" or int)

The height of each row. This can be one of the following:

  • "content" (default): Each row is as tall as its tallest cell.
  • A positive integer: Every row is that many pixels. Content that is taller scrolls inside the cell. Content does not stretch automatically. Pass height="stretch" to a chart or dataframe to fill the cell, either as a direct child of the grid or inside grid.cell().

width ("stretch" or int)

The width of the grid. This can be one of the following:

  • "stretch" (default): The width of the grid matches the width of the parent container.
  • An integer specifying the width in pixels: The grid has a fixed width. If the specified width is greater than the width of the parent container, the width of the grid matches the width of the parent container.

height ("content", "stretch", or int)

The height of the grid. This can be one of the following:

  • "content" (default): The height of the grid matches the height of its content.
  • "stretch": The height of the grid matches the height of its content or the height of the parent container, whichever is larger. If the grid is not in a parent container, the height of the grid matches the height of its content.
  • An integer specifying the height in pixels: The grid has a fixed height. If the content is larger than the specified height, scrolling is enabled.

key (str, int, or None)

An optional string or integer to give this element a stable identity. If this is None (default), the element's identity will be determined based on the values of the other parameters.

Additionally, if key is provided, it will be used as a CSS class name prefixed with st-key-.

dense (bool)

Whether later cells can backfill holes left by spanning cells. If this is False (default), cells keep source order. If this is True, later cells can appear visually ahead of earlier ones. That can hurt accessibility, because keyboard and screen-reader order stay in source order.

Returns

(GridContainer)

A container that supports with notation or method calls. It also has a cell() method for grouping elements and spanning columns or rows.

Examples

Example 1: Metric cards

import streamlit as st

metrics = [
    ("Revenue", "$1.2M", "+8%"),
    ("Pipeline", "$4.8M", "+12%"),
    ("Conversion", "12.4%", "+1.1%"),
    ("Retention", "96%", "-0.4%"),
]
grid = st.grid(4)
for label, value, delta in metrics:
    grid.metric(label, value, delta, border=True)

Example 2: Full-width cell

import streamlit as st

grid = st.grid("auto", min_column_width=220)
with grid.cell(column_span="all"):
    st.markdown("**Featured**")
grid.markdown("Card")

Example 3: Fixed column count (no wrap)

import streamlit as st
from numpy.random import default_rng as rng

df = rng(0).standard_normal((20, 3))
grid = st.grid(3, wrap=False, border=True)
grid.line_chart(df, height=220)
grid.bar_chart(df, height=220)
grid.dataframe(df, height=220)

Create the next auto-placed grid cell.

With no arguments this groups multiple elements into one cell. column_span and row_span occupy more tracks. The returned object works with with notation or method chaining.

Function signature[source]

GridContainer.cell(*, column_span=1, row_span=1)

Parameters

column_span (int or "all")

The number of columns the cell spans. This can be one of the following:

  • A positive integer (default is 1): The cell spans this many columns. If the grid wraps to fewer columns, the span shrinks to fit. If columns is an integer, this can't exceed it.
  • "all": The cell spans every column on its own row.

row_span (int)

The number of rows the cell spans. Defaults to 1. Must be a positive integer. With row_height="content", the rows it covers grow to fit this cell. With a pixel row_height, the cell covers that many row tracks plus the gaps between them.

Returns

(DeltaGenerator)

A container object that supports with notation or method calls.

Examples

Group a metric and caption in one cell, and span a featured card.

import streamlit as st

grid = st.grid(4)
with grid.cell():
    st.metric("Revenue", "$1.2M", "+8%", border=True)
    st.caption("Trailing 30 days")
with grid.cell(column_span="all"):
    st.markdown("**Featured**")
forum

Still have questions?

Our forums are full of helpful information and Streamlit experts.