Output Formats
Elements produces HTML strings. The exact shape depends on the wrapper: <Email>, <Page>, <Document>, or <Body mode="...">. Same component tree, different output.
Format Matrix
| Wrapper | mode | Layout primitive | Targeted at |
|---|---|---|---|
<Email> | "email" | <table> | Outlook, Gmail, Yahoo, Apple Mail |
<Page> | "web" | <div> + flexbox | Modern browsers |
<Document> | "document" | <div> | PDF engines, print preview |
<Body> | configurable | depends on mode | Advanced — when mode is dynamic |
You never write <table> or <div> yourself. The wrapper picks the right primitive.
<Email> — Table-based HTML
Email clients are notoriously fragmented. Outlook on Windows still uses Microsoft Word's rendering engine. Gmail strips many CSS features. Some clients support media queries, others don't. Table-based HTML is the industry-standard way to survive all of that, and <Email> produces it for you.
Example
import {
Email,
Row,
Column,
ColumnLayouts,
Paragraph,
renderToHtmlParts,
} from '@unlayer/react-elements';
const { head, body } = renderToHtmlParts(
<Email previewText="Your weekly digest">
<Row layout={ColumnLayouts.OneColumn} padding="20px">
<Column>
<Paragraph fontSize="16px">Hello there!</Paragraph>
</Column>
</Row>
</Email>,
);
const html = `<!DOCTYPE html><html><head>${head}</head>${body}</html>`;
<Email> also renders the previewText prop as an invisible padded element at the top of the body. That's what controls the preview shown next to the subject line in most inboxes.
Pipe the assembled html straight into Resend, SendGrid, SES, Postmark, Nodemailer, or any other ESP. Prefer renderToHtmlParts over renderToHtml so the <style> block lands in <head>. See Rendering API.
<Page> — Responsive Web HTML
For a browser viewport, tables are the wrong tool. <Page> emits modern HTML using div + flexbox.
Example
import {
Page,
Row,
Column,
ColumnLayouts,
Heading,
Paragraph,
renderToHtml,
} from '@unlayer/react-elements';
const html = renderToHtml(
<Page contentWidth="1200px">
<Row layout={ColumnLayouts.TwoEqual} padding="40px">
<Column>
<Heading headingType="h1" fontSize="32px">
Elements
</Heading>
</Column>
<Column>
<Paragraph fontSize="16px">Build with code, render anywhere.</Paragraph>
</Column>
</Row>
</Page>,
);
Use <Page> for landing pages, web archive copies of email campaigns, and HTML previews shown inside a webview.
<Document> — Print / PDF HTML
<Document> emits HTML tuned for print: a layout that respects page boundaries, plays well with print stylesheets, and pairs cleanly with headless-browser PDF generators.
Example with Puppeteer
import puppeteer from 'puppeteer';
import {
Document,
Row,
Column,
ColumnLayouts,
Heading,
Paragraph,
renderToHtml,
} from '@unlayer/react-elements';
const html = renderToHtml(
<Document contentWidth="8.5in">
<Row layout={ColumnLayouts.OneColumn} padding="40px">
<Column>
<Heading headingType="h1" fontSize="28px">
Invoice #1042
</Heading>
<Paragraph fontSize="14px">Issued on 2026-05-05</Paragraph>
</Column>
</Row>
</Document>,
);
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setContent(html);
const pdf = await page.pdf({ format: 'Letter' });
await browser.close();
<Body mode="..."> — Programmatic Mode
When the rendering target is decided at runtime (a single endpoint that emits the same content as either email or web), use <Body> directly:
import {
Body,
Row,
Column,
Paragraph,
renderToHtml,
} from '@unlayer/react-elements';
function render(target: 'email' | 'web' | 'document') {
return renderToHtml(
<Body mode={target}>
<Row>
<Column>
<Paragraph>Hello</Paragraph>
</Column>
</Row>
</Body>,
);
}
The wrapper threads the resolved mode into every nested Row, Column, and item.
Bundle Characteristics
| Property | Value |
|---|---|
| Side effects | None (sideEffects: false) |
| Tree-shaking | Yes |
| Client-side runtime needed | None |
| Module format | ESM (with CJS fallback) |
There's no client-side React runtime in the output, so the resulting HTML works in environments that can't run JavaScript at all (most email clients, PDF engines).
See Also
- Wrappers — picking the right wrapper
- Rendering API —
renderToHtmlPartsis the recommended API for email - Limitations — what is not supported in each format