Layout
StableThe structural layer between tokens and components. Controls how sections, containers, grids, and stacks arrange content on the page.
The Four-Layer Mental Model
Every page section nests these four layers in order. Each layer has one job and should never do another layer's job.
<section class="vi-section vi-section--subtle"> ← bg color + vertical padding
<div class="vi-container"> ← max-width + horizontal gutters
<div class="vi-grid vi-grid--3"> ← column structure
<article class="vi-card vi-card--raised"> ← component
...
</article>
</div>
</div>
</section>
Never put layout responsibilities (margin, padding, width, grid) on a component class. Never put component styles on a layout class. If you're adding margin-top to a vi-card, stop — a layout class should handle that.
vi-section
Full-width horizontal bands. Controls vertical padding and background color. Use <section>, <header>, or <footer> — not <div> when the semantic element applies.
Background variants
vi-section--white
vi-section--subtle
vi-section--dark
vi-section--brand
<section class="vi-section vi-section--white">...</section> <section class="vi-section vi-section--subtle">...</section> <section class="vi-section vi-section--dark">...</section> <section class="vi-section vi-section--brand">...</section>
Size variants (vertical padding)
<section class="vi-section vi-section--sm">...</section> <section class="vi-section">...</section> <section class="vi-section vi-section--lg">...</section>
vi-container
Centers content and constrains max-width. Always lives inside a vi-section. Never use a container without a section wrapper.
<!-- Default: 1200px max-width --> <div class="vi-container">...</div> <!-- Narrow: 800px — for blog posts, article text --> <div class="vi-container vi-container--narrow">...</div> <!-- Wide: 1440px — for large image layouts --> <div class="vi-container vi-container--wide">...</div>
vi-section-header
Centered intro block for section headings. Optional — not every section needs one. Place it directly inside vi-container, before the grid.
Our Services
We help brands communicate clearly and consistently across every touchpoint, from strategy through execution.
<section class="vi-section vi-section--subtle">
<div class="vi-container">
<div class="vi-section-header">
<span class="vi-badge vi-badge--brand">What We Do</span>
<h2 class="vi-section-header__title">Our Services</h2>
<p class="vi-section-header__text">Supporting copy here.</p>
</div>
<div class="vi-grid vi-grid--3">
<!-- cards go here -->
</div>
</div>
</section>
vi-grid
CSS Grid column layouts. Collapses to a single column on mobile. Always lives inside vi-container.
Equal columns
<div class="vi-grid vi-grid--2">...</div> <div class="vi-grid vi-grid--3">...</div> <div class="vi-grid vi-grid--4">...</div>
Asymmetric splits
For hero sections with image + text, or content + sidebar layouts.
<!-- 66% content + 33% sidebar -->
<div class="vi-grid vi-grid--2-1">
<div>Main content</div>
<aside>Sidebar</aside>
</div>
<!-- 60% text + 40% image -->
<div class="vi-grid vi-grid--3-2">
<div class="vi-stack">
<h2>Heading</h2>
<p>Copy...</p>
<a class="vi-btn vi-btn--primary">CTA</a>
</div>
<div class="vi-ratio vi-ratio--4-3">
<img src="..." alt="...">
</div>
</div>
Auto-fill grid
The browser fills as many columns as fit at a minimum of 280px. Best for card grids where you don't want to worry about breakpoints.
<div class="vi-grid vi-grid--auto"> <!-- fills columns at min 280px — responsive automatically --> <article class="vi-card vi-card--raised">...</article> <article class="vi-card vi-card--raised">...</article> <article class="vi-card vi-card--raised">...</article> </div>
vi-stack
Adds consistent vertical spacing between sibling elements. Use inside a grid column to space headings, paragraphs, and buttons — no manual margins needed.
<div class="vi-grid vi-grid--3-2">
<!-- Left column: stacked text + CTA -->
<div class="vi-stack">
<span class="vi-badge vi-badge--brand">New</span>
<h1>Page Heading</h1>
<p>Supporting subtext that describes the value proposition.</p>
<div class="vi-row">
<a class="vi-btn vi-btn--primary vi-btn--lg">Get Started</a>
<a class="vi-btn vi-btn--ghost vi-btn--lg">Learn More</a>
</div>
</div>
<!-- Right column: image -->
<div class="vi-ratio vi-ratio--4-3">
<img src="hero.jpg" alt="...">
</div>
</div>
Full page example
A complete page using every layout layer together. This is the pattern for a typical marketing page or WordPress template.
<!-- HERO -->
<section class="vi-section vi-section--lg vi-section--dark">
<div class="vi-container">
<div class="vi-grid vi-grid--3-2">
<div class="vi-stack">
<span class="vi-badge vi-badge--info">Now Available</span>
<h1>We Build Brands That Last</h1>
<p>Strategy, design, and execution for growing companies.</p>
<div class="vi-row">
<a href="/contact" class="vi-btn vi-btn--primary vi-btn--lg">Start a Project</a>
<a href="/work" class="vi-btn vi-btn--ghost vi-btn--lg">See Our Work</a>
</div>
</div>
<div class="vi-ratio vi-ratio--4-3">
<img src="hero.jpg" alt="VI team at work">
</div>
</div>
</div>
</section>
<!-- SERVICES -->
<section class="vi-section vi-section--subtle">
<div class="vi-container">
<div class="vi-section-header">
<span class="vi-badge vi-badge--brand">What We Do</span>
<h2 class="vi-section-header__title">Our Services</h2>
<p class="vi-section-header__text">Full-service brand and digital.</p>
</div>
<div class="vi-grid vi-grid--3">
<article class="vi-card vi-card--raised">...</article>
<article class="vi-card vi-card--raised">...</article>
<article class="vi-card vi-card--raised">...</article>
</div>
</div>
</section>
<!-- RECENT WORK -->
<section class="vi-section vi-section--white">
<div class="vi-container">
<div class="vi-section-header vi-section-header--left">
<h2 class="vi-section-header__title">Recent Work</h2>
<p class="vi-section-header__text">Selected projects.</p>
</div>
<div class="vi-grid vi-grid--auto">
<article class="vi-card vi-card--raised vi-card--interactive">...</article>
<article class="vi-card vi-card--raised vi-card--interactive">...</article>
<article class="vi-card vi-card--raised vi-card--interactive">...</article>
<article class="vi-card vi-card--raised vi-card--interactive">...</article>
</div>
</div>
</section>
<!-- CTA BAND -->
<section class="vi-section vi-section--brand">
<div class="vi-container vi-container--narrow">
<div class="vi-section-header">
<h2 class="vi-section-header__title">Ready to get started?</h2>
<p class="vi-section-header__text">Let's build something great together.</p>
<div class="vi-row">
<a href="/contact" class="vi-btn vi-btn--primary"
style="background:white; color:var(--color-interactive-default);">
Contact Us
</a>
</div>
</div>
</div>
</section>
Class reference
Section
| Class | Description |
|---|---|
| vi-section | Base. Full-width band, standard vertical padding (64px). |
| vi-section--sm | Compact padding (48px). Tight sections, footer areas. |
| vi-section--lg | Large padding (96px). Hero sections, feature highlights. |
| vi-section--flush | No padding. For full-bleed image sections. |
| vi-section--white | White background. |
| vi-section--subtle | Light grey background. Alternates visual weight. |
| vi-section--dark | Dark background, light text. |
| vi-section--brand | Brand color background, white text. |
Container
| Class | Description |
|---|---|
| vi-container | 1200px max-width, centered, responsive gutters. |
| vi-container--narrow | 800px max-width. Blog posts, article body. |
| vi-container--wide | 1440px max-width. Large image layouts. |
| vi-container--full | No max-width constraint. |
Section Header
| Class | Description |
|---|---|
| vi-section-header | Centered intro block. Flex column with gap. |
| vi-section-header--left | Left-aligned variant. |
| vi-section-header__title | Section heading (use h2). |
| vi-section-header__text | Supporting subtext below heading. |
Grid
| Class | Columns | Responsive |
|---|---|---|
| vi-grid--2 | 2 equal | → 1 col at 768px |
| vi-grid--3 | 3 equal | → 2 col at 1024px → 1 col at 768px |
| vi-grid--4 | 4 equal | → 2 col at 1024px → 1 col at 768px |
| vi-grid--2-1 | 66% / 33% | → 1 col at 768px |
| vi-grid--1-2 | 33% / 66% | → 1 col at 768px |
| vi-grid--3-2 | 60% / 40% | → 1 col at 768px |
| vi-grid--2-3 | 40% / 60% | → 1 col at 768px |
| vi-grid--auto | Auto-fill at 280px min | Automatic |
| vi-grid--gap-sm | 16px gap (modifier, combine with any grid) | |
| vi-grid--gap-lg | 32px gap (modifier, combine with any grid) | |
Stack
| Class | Description |
|---|---|
| vi-stack | 24px top margin between siblings. Default. |
| vi-stack--sm | 16px gap. Tight stacks, caption text. |
| vi-stack--lg | 32px gap. Loose stacks, major content sections. |
Row & Utilities
| Class | Description |
|---|---|
| vi-row | Flex row, centered vertically, 16px gap. |
| vi-row--wrap | Allows items to wrap to next line. |
| vi-row--center | Justify center. |
| vi-row--between | Space between. |
| vi-row--end | Justify end. |
| vi-ratio--16-9 | 16:9 aspect ratio box. |
| vi-ratio--4-3 | 4:3 aspect ratio box. |
| vi-ratio--1-1 | Square aspect ratio box. |
| vi-divider | Horizontal rule using border token. |