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';Outer frame (wrapper)
To frame a section in a full-width 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:
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.