Skip to content
Primitiv home
Framework
Consumption mode

Container

stableSource Figma

A centred, max-width content column with token-bound inline gutters. size caps the width against the breakpoint scale and gutter sets the inline padding — responsive (the default) escalates it at the md and lg breakpoints, the fixed steps pin one value at every width. No inline styles: both props are curated presets.

Playground

Density

Preview

gutter=responsive
Gutter
import { Container } from "@/components/ui/container";
<Container gutter="responsive">  {/* page content */}</Container>

Density is set by a data-density ancestor — the Context system, not a Container prop.

Installation

npx primitiv add container

Import

import { Container } from "@/components/ui/container";

No headless primitive — this one ships only as a copied styled surface, so primitiv add is the only way in, whichever mode you are reading.

Props

Container

Extends HTMLDivElement — every native attribute of that element is accepted and forwarded.

PropTypeDefaultDescription
asChildbooleanRender the single child element instead of a wrapping <div>, merging the container classes onto it — e.g. <Container asChild><main>...</main></Container>.
size"xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "full"lgThe width the content column stops growing at, resolved against the breakpoint scale so size="lg" caps exactly where the lg breakpoint begins.
gutter"responsive" | "none" | "sm" | "md" | "lg"responsiveInline padding between the content column and its edges. Each step is a density-scaled Context token.

Styling contract

--primitiv-container-max-width--primitiv-container-gutter

Accessibility

  • Container renders a plain <div> — it is layout, not structure. Use asChild to render the real landmark it usually wraps (<main>, <header>) rather than nesting one inside an anonymous <div>.
  • Capping the line length is itself an accessibility win: over-long lines are hard to track back to the next line, so a md-width reading column helps low-vision and dyslexic readers, not just aesthetics.
  • It adds no interactive or ARIA surface of its own; the semantics come from what you put inside it.

Examples

Capping the content width

The Container's main job: cap how wide content can grow and centre it, so a long line of text never runs the full width of a large monitor. size picks the cap from the breakpoint scale — md for a reading column, xl/2xl for an app shell, full to opt out. It centres itself, so you do not add margins.

Density
A capped, centred column
import { Container } from "@/components/ui/container";
<Container size="md">  <article>{/* a comfortable reading column */}</article></Container>

Gutters

gutter is the inline padding that keeps content off the screen edges on narrow viewports. The default responsive starts tight and escalates at the md and lg breakpoints, which is what you want for a page shell; the fixed steps (sm/md/lg) pin one value at every width, and none removes it for a Container that sits inside something already padded.

Density
Inset from the edges by the gutter
import { Container } from "@/components/ui/container";
<Container gutter="responsive">{/* escalates at md / lg */}</Container><Container gutter="lg">{/* a fixed, generous inset */}</Container><Container gutter="none">{/* already padded by a parent */}</Container>