English
Sections and Columns
The SectionBlock is the layout primitive in Templatical. Every multi-column layout is built by creating a section and placing blocks inside its columns.
Column layouts
Email best practice
Stick to 1-2 columns for most emails. Three-column layouts become cramped on mobile when columns stack vertically, and some email clients handle 3-column layouts inconsistently.
The columns property accepts one of five layout presets:
| Value | Description | Column widths |
|---|---|---|
'1' | Single column | 100% |
'2' | Two equal columns | 50% / 50% |
'3' | Three equal columns | 33% / 33% / 33% |
'2-1' | Two-thirds / one-third | 66% / 33% |
'1-2' | One-third / two-thirds | 33% / 66% |
ts
type ColumnLayout = '1' | '2' | '3' | '2-1' | '1-2';Creating sections
Use createSectionBlock from @templatical/types:
ts
import {
createSectionBlock,
createTitleBlock,
createParagraphBlock,
createImageBlock,
} from '@templatical/types';
// Empty two-column section
const section = createSectionBlock({ columns: '2' });
// Section with pre-populated columns
const hero = createSectionBlock({
columns: '1-2',
children: [
[createImageBlock({ src: 'https://cdn.example.com/logo.png', width: 120 })],
[
createTitleBlock({ content: '<h1>Welcome</h1>', level: 1 }),
createParagraphBlock({ content: '<p>Get started in minutes.</p>' }),
],
],
});The children array
children is a Block[][] -- an array of arrays. Each inner array represents the blocks inside one column, ordered left to right.
ts
// For a '2' layout:
section.children = [
[blockA, blockB], // Left column
[blockC], // Right column
];
// For a '3' layout:
section.children = [
[blockA], // Left
[blockB], // Center
[blockC], // Right
];The length of children must match the number of columns in the chosen layout. When you change columns, the editor automatically adjusts children -- merging excess columns into the last column or adding empty arrays for new columns.
Adding blocks to columns
To programmatically add a block to a specific column:
ts
// Add a button to the second column (index 1)
section.children[1].push(
createButtonBlock({
text: 'Learn More',
url: 'https://example.com/docs',
}),
);Nesting
Sections cannot be nested inside other sections. Each section sits at the top level of the template's block list. Within a column, you can place any non-section block type: titles, paragraphs, images, buttons, tables, custom blocks, and so on.
Responsive behavior
On desktop, columns render side-by-side at their defined widths. On smaller screens, columns stack vertically in source order (left column on top) — MJML's default.
stackOnMobile opts out. Omit it or set true to keep stacking. false wraps the columns in <mj-group> so they stay side by side on mobile. The section toolbar exposes the toggle on multi-column sections. A one-column section never emits mj-group.
ts
const row = createSectionBlock({ columns: '2', stackOnMobile: false });You can use the visibility property on individual blocks within columns to show or hide content per breakpoint:
ts
const block = createParagraphBlock({
content: '<p>Desktop only sidebar content</p>',
});
block.visibility = {
desktop: true,
mobile: false,
};See Styling for more on block visibility.
Section-level styles
Sections support the same BlockStyles as other blocks. Common use cases include setting a background color or padding on the entire row:
ts
const section = createSectionBlock({ columns: '1' });
section.styles = {
backgroundColor: '#f8fafc',
padding: { top: 32, right: 24, bottom: 32, left: 24 },
};Sections also accept a borderRadius (in px, a section-specific property) for rounded corners — useful for a card-style section on a contrasting background:
ts
const card = createSectionBlock({ columns: '1', borderRadius: 12 });
card.styles.backgroundColor = '#ffffff';Background image
A section's backgroundImage paints an image behind its columns. Set styles.backgroundColor as well, as the fallback while the image loads and in clients that don't show background images. In the editor's Background panel you also choose the size (Fill, Fit or Original), a nine-point position and whether the image repeats. See the Section block for the email client notes on background images.
Outer frame (wrapper)
To frame a section in a colored band — e.g. a white card sitting on a blue background — set wrapper. It renders an mj-wrapper around the section, with its own background, padding, and corner radius. The band is as wide as the email body (settings.width), not the recipient's whole window:
ts
const card = createSectionBlock({ columns: '1', borderRadius: 12 });
card.styles.backgroundColor = '#ffffff';
card.wrapper = {
backgroundColor: '#1e3a8a',
padding: { top: 24, right: 24, bottom: 24, left: 24 },
borderRadius: 16,
};The wrapper's padding is what makes the band show around the section. In the editor, enable it from the Wrapper panel in the section toolbar. The wrapper is a styling layer, not a container — sections still cannot be nested. An embedder-owned card around the authored sections is a layout overlay.