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.

Use flush sparingly. Without padding, content can collide with the viewport edge on small screens. Flush is intended for advanced layouts where a parent element (e.g. the main content area of an app shell) manages its own padding.

Anatomy

  • Container wrapper — a <div> with mx-auto w-full for centring
  • Max-width bound — a max-w-screen-{size} class that caps the container width
  • Responsive gutters — px-4 sm:px-6 lg:px-8 horizontal padding, removed when flush is 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 sm or md for forms, auth, and settings pages
  • Use xl for standard product pages
  • Use 2xl or full for data-heavy dashboards and app shells
  • Use flush only 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 sm or md for forms and settings pages
  • Use xl for standard product pages
  • Use 2xl or full for data-heavy dashboards
  • Use flush only 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 full width 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 get role="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 lg and 2xl is most visible above 1280 px. Preview your page at 1920 px to verify the container width suits the content.
  • Use flush with parent-shell layouts. When the Container sits inside an app shell that already applies px-* padding at a higher level, set flush to 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 with max-w-* utilities.
  • Choosing full for readable text pages — long lines of text (120+ characters) are hard to read. Use lg or md for 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 flush removes 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 full only for app shells or data-heavy views. Reserve full for 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 size and flush values.
  • 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/react or @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 lg to 2xl depending 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" flush container 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
  • 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

Use the canonical Container HTML classes and data attributes shown in the examples on this page. React and Vue adapters expose the same visual contract through framework-native props and events where the package implements an adapter.

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