Page grid and containers
The page grid, the content column, sections and centered content, for marketing and content pages.
The page grid is the set of columns, gutters and side padding a marketing or content page snaps to, which changes at 640px and 1024px of the page's width. Build such a page from Page, Section and Container, and its columns, padding and headlines follow the room it has.
The grid
| Page width | Columns | Gutter | Side padding |
|---|---|---|---|
| Under 640px | 4 | 16px | 16px |
| 640px to 1023px | 8 | 24px | 24px |
| 1024px and up | 12 | 24px | 32px |
Content stays at most 1200px wide (--bt-w-page), centered. Visuals may run past the content column to the window's edge; text never does.
Seeing the columns. In development, ⌥⇧G shows the columns over the page.
The parts
Page
The page itself: a column of sections, and the container the grid, the side padding and the display type follow. A page reads the same in a window and in a panel as wide.
Section
A band of the page: room above and below, an optional title and body, and its content in a
Container. Its room steps down a size on a phone, so padding never outweighs content.Container
The content column: at most 1200px wide, centered with padding rather than margins.
Center
Centers its content on both axes in the space it's given, such as an empty state on a stage.
An about page with one large section:
import type { ReactElement } from "react";
import { Page, Section } from "@butteryui/react";
import { Text } from "@butteryui/core";
export function About(): ReactElement {
return (
<Page>
<Section
size="lg"
title="Roasted to order"
body="Every bag is roasted the week it ships."
>
<Text variant="body">Our roastery is in Portland.</Text>
</Section>
</Page>
);
}App screens. Use AppShell and AppPage instead, with the same side padding.
Page
When to use it
Use it for
- A landing page, a product page or an article
- Any page built from Section, SplitHero, Bento and the other page patterns
Not for
- App screens: use AppShell
Examples
Article page
A single long section of reading on a page, its headline sized by the page's own width.
Designing a title slide
Start with the words. A good title fits on one line, big enough to read from the back of the room.
Landing page
A page as the main landmark, its sections taking turns on the two backgrounds, with prices by the billing period.
Decks that look designed
Write the slides, pick a theme, present.
One price, every feature
$12 a month
Variants and states
Sections on a page
The page is the size container: headlines and padding follow its width, not the window's.
Made for meeting days
One deck for the projector, the call and the inbox.
Kept in step
Undo and redo remember every change.
Props
Page
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | boolean | Render the single child element, such as a main, instead of a div, with Page's props merged onto it. |
It also takes ComponentPropsWithRef<"div">.
Accessibility
No role of its own. Put what sits between the NavBar and the Footer in a main element and give the bar skipTo with its id, as the marketing template does; on a page with no bar or footer, pass asChild with a main instead.
It takes no keyboard input of its own.
Motion
It doesn't move.
With reduced motion: Nothing changes.
Layout
It takes its container's width as a column of sections on the surface background, and it's the size container the page grid follows: the side padding inside it (16, 24 or 32px) and the display type step up as its own width passes 640 and 1024px. It sets no height, truncates nothing and has no hit areas of its own.
Related
See it in the Halfmoon shop demo.
Section
When to use it
Use it for
- Each band of a landing or product page
- Setting a band apart with tone="muted"
Not for
- Grouping controls in an app: use Inspector.Section
- A hero: use SplitHero or CenteredHero, which are sections already
Examples
Band sizes
The three sizes and two tones of a band: pick one of each and the band's room and background follow.
Made for meeting days
96px above and below, on the page's surface.
Feature band
A titled band with three equal tiles.
Everything a slide needs
A theme, a background, a layout and speaker notes, all in one panel.
New templates
A templates page's band: a heading over this week's three new templates, each added to the library from its card.
New this week
Three templates, each a deck you can make your own.
Numbers, charts and a summary
Agenda, schedule and a map
Roles, timeline and budget
0 templates in your library
Quiet band
A small centered band on the app background, between two louder ones.
Kept in step
Undo and redo remember every change.
Variants and states
Heading, body and content
The heading and body sit 48px above the content, 64 once the page is past 1024px.
Everything a slide needs
A theme, a background, a layout and speaker notes, all in one panel.
Centered and muted
Kept in step
Undo and redo remember every change.
Props
Section
| Prop | Type | Default | Description |
|---|---|---|---|
size | "sm" | "md" | "lg" | "md" | Room above and below: "sm" (64px), "md" (96px, the default) or "lg" (128px). |
tone | "default" | "muted" | "default" on the surface, or "muted" on the app background, to set a section apart. | |
title | ReactNode | The section's heading. It names the section for screen readers. | |
body | ReactNode | A line or two under the heading. | |
align | "start" | "center" | "start" | Where the heading and body sit: "start" (the default) or "center". |
contained | boolean | true | Whether the content sits in a Container. Defaults to true; turn it off for full-bleed content. |
It also takes Omit<ComponentPropsWithRef<"section">, "title">.
Accessibility
A section landmark named by its heading when it has one; the heading is an h2.
It takes no keyboard input of its own.
Motion
It doesn't move.
With reduced motion: Nothing changes.
Layout
Its height is its content plus its room: 96px above and below by default, 64 with size="sm" and 128 with "lg", and inside a Page under 640px wide the default and "lg" take a step less. It fills its parent's width and puts its content in a Container, at most 1200px wide with the page's side padding; the heading and body wrap, 48px above the content (64 from 1024px of page), or with no gap under them when nothing follows, so they sit in the middle of the band; it has no hit areas of its own.
Related
See it in the Halfmoon shop demo.
Container
When to use it
Use it for
- Content on a page that isn't in a Section, such as a header row
- Your own band of a page with
contained={false}on its Section
Not for
- A Section's content: Section already puts it in a Container
- App screens: use AppShell and its panels
Examples
Full bleed band
A band whose background runs edge to edge while its words stay in the column.
Every deck you make keeps its own history.
Page header row
A row across the top of a page, lined up with the sections under it.
Deckhand
Start a deckVariants and states
A centered column
At most 1200px wide, with 16, 24 or 32px at the sides as the page passes 640 and 1024px.
Props
Container
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | boolean | Render the single child element instead of a div, with Container's props merged onto it. |
It also takes ComponentPropsWithRef<"div">.
Accessibility
A plain element with no role; pass asChild to make a landmark of it.
It takes no keyboard input of its own.
Motion
It doesn't move.
With reduced motion: Nothing changes.
Layout
It's as wide as its parent and centers a column at most 1200px wide (--bt-w-page) with side padding rather than margins: 16px a side, 24 from 640px of page and 32 from 1024px, more on a page wider than the column.
Related
Center
When to use it
Use it for
- Empty states and loading states inside a stage or panel
Not for
- Centering text inside a control: controls already center their content
Examples
Loading panel
A short status message in the middle of a panel while its content loads.
Loading your decks…
Stage empty
A stage that holds its empty state in the middle, and then the slide that takes its place.
Your canvas is empty
Add a slide, or open a deck from your library.
Variants and states
Both axes
Content sits in the middle of whatever space Center gets.
Props
Center
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | boolean | Render the single child element instead of a div, with Center's props merged onto it. | |
pad | SpaceValue | Padding on every side. | |
padX | SpaceValue | Left and right padding. Wins over pad on those sides. | |
padY | SpaceValue | Top and bottom padding. Wins over pad on those sides. |
It also takes ComponentPropsWithRef<"div">.
Accessibility
No role of its own.
It takes no keyboard input of its own.
Motion
It doesn't move.
With reduced motion: Nothing changes.
Layout
It's as wide as its parent and as tall as its content, or as tall as the height it's given, such as 100% of a sized panel. Its content sits in the middle on both axes and is never wider than Center. It has no hit area of its own.
Related
Related
- Responsive
Why buttery components respond to their container rather than the window, and how to do the same.
- App shell
The frame of a whole app, as an editor or a dashboard, and the page that goes in it.