---
title: Container
description: Groups blocks together with a shared border, an optional header, and a width limit.
---

`container` wraps a list of child blocks with a border and background, an optional header with an
icon, title, and subtitle, and a width variant. It can also be made collapsible. It's a library-invented
block, not part of the public `@slack/types` package.

<Preview
  payload={{
    blocks: [
      {
        type: "container",
        title: { type: "plain_text", text: "Project Updates" },
        subtitle: { type: "plain_text", text: "Last synced 5 minutes ago" },
        icon: {
          type: "image",
          image_url:
            "https://api.slack.com/img/blocks/bkb_template_images/notificationsWarningIcon.png",
          alt_text: "Project icon",
        },
        child_blocks: [
          {
            type: "section",
            text: {
              type: "mrkdwn",
              text: "*Section title*\nThis is a section block with markdown text inside the container.",
            },
          },
          { type: "divider" },
          {
            type: "context",
            elements: [{ type: "mrkdwn", text: "Last updated: May 14, 2026 at 3:42 PM" }],
          },
        ],
      },
    ],
  }}
/>

## Fields

| Prop | Type | Default | Description |
| - | - | - | - |
| `type` | `string` | - | Always `container`. |
| `title?` | `PlainTextElement \| MrkdwnElement` | - | Bold text in the header. |
| `subtitle?` | `PlainTextElement \| MrkdwnElement` | - | Muted text under the title. |
| `icon?` | `{ type: "image"; image_url: string; alt_text?: string }` | - | A 36×36 rounded icon, left of the title and subtitle. |
| `width?` | `"narrow" \| "standard" \| "wide" \| "full"` | `"standard"` | The container's max width. An unrecognized or omitted value falls back to `standard`. |
| `is_collapsible?` | `boolean` | `false` | Makes the header a toggle button with a chevron. When true, the header always renders even with no title, subtitle, or icon. |
| `default_collapsed?` | `boolean` | `false` | Starts the container collapsed. Only takes effect when `is_collapsible` is `true`. |
| `has_header_divider?` | `boolean` | `false` | Adds a border between the header and the body. |
| `child_blocks?` | `Block[]` | - | Blocks rendered inside the container. |

:::note
The header (icon, title, subtitle) only renders when at least one of those is set, or when
`is_collapsible` is `true`. A non-collapsible container with none of those fields renders no header at all.
:::

## Examples

### Widths

**standard**

<Preview
  payload={{
    blocks: [
      {
        type: "container",
        title: { type: "plain_text", text: "Standard Width Container" },
        width: "standard",
        child_blocks: [
          {
            type: "rich_text",
            elements: [
              {
                type: "rich_text_section",
                elements: [
                  { type: "text", text: "This is a simple rich text block inside a container." },
                ],
              },
            ],
          },
        ],
      },
    ],
  }}
/>

**narrow**

<Preview
  payload={{
    blocks: [
      {
        type: "container",
        title: { type: "plain_text", text: "Narrow Width Container" },
        width: "narrow",
        child_blocks: [
          {
            type: "rich_text",
            elements: [
              {
                type: "rich_text_section",
                elements: [
                  { type: "text", text: "This is a simple rich text block inside a container." },
                ],
              },
            ],
          },
        ],
      },
    ],
  }}
/>

**wide**

<Preview
  payload={{
    blocks: [
      {
        type: "container",
        title: { type: "plain_text", text: "Wide Width Container" },
        width: "wide",
        child_blocks: [
          {
            type: "rich_text",
            elements: [
              {
                type: "rich_text_section",
                elements: [
                  { type: "text", text: "This is a simple rich text block inside a container." },
                ],
              },
            ],
          },
        ],
      },
    ],
  }}
/>

**full**

<Preview
  payload={{
    blocks: [
      {
        type: "container",
        title: { type: "plain_text", text: "Full Width Container" },
        width: "full",
        child_blocks: [
          {
            type: "rich_text",
            elements: [
              {
                type: "rich_text_section",
                elements: [
                  { type: "text", text: "This is a simple rich text block inside a container." },
                ],
              },
            ],
          },
        ],
      },
    ],
  }}
/>

### Collapsible

<Preview
  payload={{
    blocks: [
      {
        type: "container",
        title: { type: "plain_text", text: "Collapsible Container" },
        is_collapsible: true,
        default_collapsed: false,
        child_blocks: [
          {
            type: "rich_text",
            elements: [
              {
                type: "rich_text_section",
                elements: [
                  { type: "text", text: "This is a simple rich text block inside a container." },
                ],
              },
            ],
          },
          {
            type: "section",
            text: {
              type: "mrkdwn",
              text: "*Section title*\nThis is a section block with markdown text inside the container.",
            },
          },
        ],
      },
    ],
  }}
/>

Set `default_collapsed: true` to start it collapsed instead.

### Header divider

<Preview
  payload={{
    blocks: [
      {
        type: "container",
        title: { type: "plain_text", text: "Header Divider Container" },
        subtitle: {
          type: "plain_text",
          text: "A visible border separates the header from the content",
        },
        has_header_divider: true,
        child_blocks: [
          {
            type: "section",
            text: {
              type: "mrkdwn",
              text: "*Section title*\nThis is a section block with markdown text inside the container.",
            },
          },
          {
            type: "context",
            elements: [{ type: "mrkdwn", text: "Last updated: May 14, 2026 at 3:42 PM" }],
          },
        ],
      },
    ],
  }}
/>

### Icon and subtitle

The preview at the top of this page shows a container with an icon, title, and subtitle together.

### Interactive children

<Preview
  actions
  payload={{
    blocks: [
      {
        type: "container",
        title: { type: "plain_text", text: "Add a teammate" },
        child_blocks: [
          {
            type: "input",
            block_id: "name",
            label: { type: "plain_text", text: "Name" },
            element: {
              type: "plain_text_input",
              action_id: "name_input",
              placeholder: { type: "plain_text", text: "Jane Doe" },
            },
          },
          {
            type: "actions",
            elements: [
              {
                type: "button",
                style: "primary",
                text: { type: "plain_text", text: "Submit" },
                action_id: "submit",
              },
              { type: "button", text: { type: "plain_text", text: "Cancel" }, action_id: "cancel" },
            ],
          },
        ],
      },
    ],
  }}
/>

A container doesn't intercept its children's interactions. An `input` or `actions` block inside it
dispatches the same `block_actions` payload it would at the top level.

## Interactivity

Interactive `child_blocks` (buttons, selects, inputs) dispatch Slack's standard `block_actions`
payload, keyed by whatever `block_id` and `action_id` that child block declares. See
[Interactivity](/guides/interactivity) for the full payload shape.

## Related

**[Callout](/blocks/callout)**

A tinted panel for grouping blocks, without a header or width control.

**[Card](/blocks/card)**

A more opinionated, fixed layout for a single piece of content.
