Container
Constrains content width and centers it.
Overview
Container is a centred page-level layout wrapper that constrains content width, caps the maximum width per breakpoint, and applies responsive horizontal padding. It gives every page a consistent content width — from auth forms and settings screens to dashboards, data tables, and app shells.
Why this exists
Without Container, every page must hardcode max-w-screen-xl mx-auto px-4 sm:px-6 lg:px-8 manually. When the design's target width changes, every page must be updated individually. Container centralises page width into a single size prop — changing the page width becomes a one-line change. It pairs with Section (vertical spacing), Stack (item flow), Grid (columns), and Card (surface) for a complete page layout system.
Mental model
Container is the page-width governor. It sits at the top of the layout hierarchy — usually a direct child of <body> or the main content area. It centres content horizontally, caps width at a chosen breakpoint, and adds breathing room on the sides. Everything inside it (sections, grids, cards, text) inherits the constrained width. Choose one size per page and do not nest Containers.
When to use
- SaaS dashboard pages — metrics, charts, and data tables in a consistent-width layout
- Admin overview pages — widget-based admin panels with mixed content density
- Settings screens — form sections at a readable width (use
size="md") - Auth pages — sign-in, sign-up, and password-reset forms at a narrow width (use
size="sm") - Ecommerce back-office pages — order lists, product tables, inventory dashboards
- ERP / POS layouts — operational views that fill the available width (use
size="full"with flush) - Documentation pages — readable body text paired with a sidebar table of contents
- Starter-kit page shells — Laravel, React, and Vue pages built on Container + Section + Stack + Card
When not to use
- Do not use Container for small spacing inside cards or form fields — use padding, Stack, or spacing utilities instead
- Do not nest Containers — one Container per page or per major layout region is enough
- Do not use Container for full-width hero sections that should bleed edge-to-edge — let the hero be a direct child of
<body>or a section outside the Container
Basic example
A default Container centres content and caps width at the xl breakpoint (1280 px). The dashed border is for illustration only.
Container — centred with responsive horizontal padding
<div class="mx-auto w-full max-w-screen-xl px-4 sm:px-6 lg:px-8">
<h1 class="text-2xl font-semibold text-foreground">Page title</h1>
<!-- page content -->
</div>
Size options
Container provides six size presets that map to Tailwind max-w-screen-* breakpoints. Choose the size that matches the content density.
| Size | Max-width class | Effective max-width | Recommended use |
|---|---|---|---|
| sm | max-w-screen-sm | 640 px | Auth forms, narrow settings panels, focused content |
| md | max-w-screen-md | 768 px | Settings pages, readable content, form sections |
| lg | max-w-screen-lg | 1024 px | Standard dashboard pages, documentation |
| xl | max-w-screen-xl | 1280 px | Default product page width |
| 2xl | max-w-screen-2xl | 1536 px | Data-heavy pages, tables, reporting screens, dashboards |
| full | max-w-full | 100 % | App shells, edge-to-edge layouts, ERP/POS workspaces |
Flush behavior
By default, Container applies px-4 sm:px-6 lg:px-8 so content never touches the viewport edge. Set flush to true to remove all horizontal padding. Use flush only when a parent layout element (such as a sidebar shell or full-width toolbar) already provides the required spacing.
Anatomy
- Container wrapper — a
<div>withmx-auto w-fullfor centring - Max-width bound — a
max-w-screen-{size}class that caps the container width - Responsive gutters —
px-4 sm:px-6 lg:px-8horizontal padding, removed whenflushis true - Data attribute —
data-bi-component="layout-container"for tooling and inspection
Usage guidelines
- Use one Container per page or per major layout region — do not nest
- Choose size based on content density, not personal preference
- Use
smormdfor forms, auth, and settings pages - Use
xlfor standard product pages - Use
2xlorfullfor data-heavy dashboards and app shells - Use
flushonly when parent layout already handles padding - Pair with Section for vertical spacing between major blocks, Stack for item flow, and Grid for multi-column layouts
Do and Don't
Do
- Use Container for page-level content width
- Choose size based on content density
- Use
smormdfor forms and settings pages - Use
xlfor standard product pages - Use
2xlorfullfor data-heavy dashboards - Use
flushonly when parent layout already handles padding
Don't
- Use Container for small spacing inside cards or form fields
- Nest Containers just to adjust padding
- Hardcode
max-w-*classes across pages when Container size exists - Use
fullwidth for long readable text unless designing an app shell - Add unnecessary ARIA roles (
role="main") to layout-only Containers
Accessibility
Container is a layout wrapper — it renders a plain <div> with no ARIA roles or attributes. It does not interfere with assistive technology.
- Use semantic elements for landmarks. Use
<main>,<section>,<header>,<nav>,<aside>, or<article>as the actual container tag when document landmarks are needed. Container provides the width constraint; semantics provide the meaning. - Do not add
role="main"to every Container. Reserve landmark roles for the structural regions of the document. A Container wrapping a sidebar should not getrole="main"— use<main>directly on the content region. - Maintain logical DOM order. Container is invisible to assistive technology. Ensure the content inside it follows a logical reading and focus order.
Customization
Override the max-width by changing the size prop. For custom widths not covered by the presets, apply a Tailwind max-w-* utility class via the standard className prop — the component uses cn() to merge classes, so your custom utilities take precedence. Padding can be removed by toggling flush and adding your own padding classes.
HTML example
<!-- Default page container -->
<div class="mx-auto w-full max-w-screen-xl px-4 sm:px-6 lg:px-8">
<h1 class="text-2xl font-semibold text-foreground">Dashboard</h1>
<!-- Section, Grid, Cards, etc. -->
</div>
<!-- Narrow auth container -->
<div class="mx-auto w-full max-w-screen-sm px-4 sm:px-6 lg:px-8">
<div class="rounded-xl border border-border bg-card p-6 shadow-sm">
<h2 class="text-xl font-semibold text-foreground mb-4">Sign in</h2>
<form class="flex flex-col gap-4">
<!-- email, password, button -->
</form>
</div>
</div>
<!-- Wide data-table container -->
<div class="mx-auto w-full max-w-screen-2xl px-4 sm:px-6 lg:px-8">
<div class="rounded-xl border border-border bg-card shadow-sm">
<!-- full-width data table -->
</div>
</div>
<!-- Flush container (no horizontal padding) -->
<div class="mx-auto w-full max-w-screen-xl">
<!-- content inside a parent that already provides padding -->
</div>
React example
import { Container, Section, Stack, Card } from '@byteion/react';
export function DashboardPage() {
return (
<Container size="2xl">
<Section>
<h1 className="text-2xl font-semibold text-foreground">Analytics</h1>
<Stack gap={4}>
<Card>
<!-- charts and metrics -->
</Card>
</Stack>
</Section>
</Container>
);
}
export function SettingsPage() {
return (
<Container size="md">
<Section>
<h2 className="text-xl font-semibold text-foreground">
Account Settings
</h2>
<form className="flex flex-col gap-4">
<!-- settings fields -->
</form>
</Section>
</Container>
);
}
export function AppShell() {
return (
<Container size="full" flush>
<div className="flex h-screen">
<!-- sidebar + main content -->
</div>
</Container>
);
}
Vue example
<script setup lang="ts">
import { Container, Section, Stack, Card } from '@byteion/vue';
</script>
<template>
<!-- Dashboard with wide container -->
<Container size="2xl">
<Section>
<h1 class="text-2xl font-semibold text-foreground">Analytics</h1>
<Stack :gap="4">
<Card>
<!-- charts -->
</Card>
</Stack>
</Section>
</Container>
<!-- Auth form with narrow container -->
<Container size="sm">
<Card class="rounded-xl border border-border p-6 shadow-sm">
<form class="flex flex-col gap-4">
<!-- sign-in fields -->
</form>
</Card>
</Container>
<!-- Settings with readable-width container -->
<Container size="md">
<Section>
<h2 class="text-xl font-semibold text-foreground">
Account Settings
</h2>
<!-- form content -->
</Section>
</Container>
</template>
API Reference
React
<Container> extends HTMLAttributes<HTMLDivElement> — all standard div attributes pass through.
| Prop | Type | Default |
|---|---|---|
| size | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'full' |
'xl' |
| flush | boolean |
false |
Vue
<Container> accepts the same props as the React version. All standard HTML attributes pass through.
| Prop | Type | Default |
|---|---|---|
| size | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'full' |
'xl' |
| flush | boolean |
false |
Developer tips
- One Container per layout region. Use a single Container at the page level. Nesting creates unnecessary markup and can produce unexpected width cascades.
- Compose, don't override. Container handles width. Section handles vertical rhythm. Stack handles item spacing. Grid handles columns. Do not combine these roles in one element.
- Test on wide screens. The difference between
lgand2xlis most visible above 1280 px. Preview your page at 1920 px to verify the container width suits the content. - Use
flushwith parent-shell layouts. When the Container sits inside an app shell that already appliespx-*padding at a higher level, setflushto avoid double padding. - Combine with Section + Stack + Grid. Container → Section → Stack/Grid → Card creates a well-structured page hierarchy.
Common mistakes
- Using Container for internal card spacing — Container is for page-level width, not for spacing inside a Card. Use padding (
p-6) or Stack inside the card. - Nesting multiple Containers unnecessarily — one Container per page is sufficient. If you need different widths for different sections, use a single Container with
size="full"and constrain individual sections withmax-w-*utilities. - Choosing
fullfor readable text pages — long lines of text (120+ characters) are hard to read. Uselgormdfor documentation and article content. - Mixing random
max-w-*utilities across pages — when every page hardcodes its own max-width, the product looks disjointed. Stick to the Container size presets for visual consistency. - Forgetting that
flushremoves horizontal padding — on small screens, a flushed container without parent padding causes content to touch the viewport edge. Always verify the parent layout provides padding when using flush. - Adding
role="main"to every Container —role="main"should be on the<main>semantic element, not on a layout wrapper that happens to contain the main content.
Production usage tips
- Keep page width consistent across repeated product screens. All dashboard pages should use the same size. All settings pages should use the same size. Consistency builds a predictable user experience.
- Test mobile, tablet, and desktop widths. Verify the container's max-width and responsive padding work correctly at 375 px, 768 px, 1024 px, 1280 px, and 1920 px.
- Use
fullonly for app shells or data-heavy views. Reservefullfor edge-to-edge layouts like ERP workspaces, POS terminals, and shell frameworks that embed their own chrome. - Keep React / Vue props aligned with core HTML examples. The canonical HTML rendering is the source of truth. Ensure all three frameworks produce the same visual output for the same
sizeandflushvalues. - Validate dark mode and branded themes. Container itself uses no colour tokens, but its children do. Test inside Section, Card, and other primitives under all themes.
- For Laravel / server-rendered apps — use the raw HTML structure shown in the HTML example. Container is a zero-JS component — the
data-bi-component="layout-container"attribute is for documentation and debugging only. - For React / Vue SPAs — import from
@byteion/reactor@byteion/vue. Pair Container with Section, Stack, and Grid for full page hierarchy.
Premium examples
Pro patterns available in Byteion Pro:
- Dashboard shell with responsive content rails — sidebar navigation, top toolbar, and a Container-based main area that adapts from
lgto2xldepending on the view - Ecommerce admin layout with filters and data table — filters sidebar + data table with
size="2xl"container, sticky toolbar, and paginated results - ERP workspace with sticky toolbar —
size="full" flushcontainer with sticky toolbar, side panels, and scrollable content zones - POS management page shell — full-width Container with a flush layout for maximised operational screen real estate
- Settings layout with sidebar and constrained content — sidebar navigation with a
size="md"container for the settings form panels - Documentation page layout — sidebar TOC +
size="lg"container for comfortable reading width
Related components
- Grid — two-dimensional layout for dashboards and card grids within a Container
- Stack — one-dimensional vertical or horizontal layout within a Container
- Section — vertical spacing between major content areas within a Container
- Card — surface container for grouping related content inside a Container
API Reference
Related components
Pair this component with adjacent Byteion primitives from the same workflow: form controls for data entry, feedback components for validation, and layout primitives for spacing.
Runtime events
Byteion keeps framework APIs idiomatic: HTML uses DOM custom events, React uses callback props, and Vue uses emitted events / v-model updates.
HTML / JS events
No HTML runtime events are declared by this adapter.
React callbacks
No React callback events are declared by this adapter.
Vue emits
No Vue emitted events are declared by this adapter.
Remote / AJAX
This component does not implement Byteion JS remote loading. Use normal HTML form submission, framework state, or your application data layer around it.
Unlock Premium Patterns
Get access to copy-paste ready Pro blocks, SaaS templates, and advanced component patterns.
Explore Pro Components