Limitations
Elements covers most email/page/document use cases out of the box, but it isn't a fully general HTML renderer. Some constraints come from how the library is structured, others come from the reality of how email clients render HTML. This page collects both.
Structural Constraints
The tree must follow this shape exactly:
<Email | Page | Document | Body>
<Row>
<Column>
...content components...
</Column>
</Row>
</...>
Concretely:
- Content components must live inside a
<Column>. They cannot sit directly inside a<Row>or a root wrapper. <Column>must live inside a<Row>. It cannot sit directly in a wrapper.<Row>must live inside a wrapper (<Email>,<Page>,<Document>, or<Body>).- The
<Column>count must match the chosenlayout(or the length ofcells). Mismatch throws viavalidateColumnLayout. renderToJsonrequires the root to be<Body>,<Email>,<Page>, or<Document>. Any other root throws.renderRowToJsonrequires the root to be<Row>. Any other root throws.
Common Mistakes
The footguns we see most often. Each one maps to a Critical Rule in Configuration.
fontFamilyas a string. Must be{ label: string, value: string }, never a plain string.fontWeightas a string. Must be a number (400,700), never"400".- Column count mismatch.
TwoEqualwants two<Column>children,ThreeEqualwants three, and so on. - Items rendered directly in
<Row>. Wrap them in a<Column>first. - Columns rendered directly in a wrapper. Wrap them in a
<Row>first. textprop on<Paragraph>. Usehtml(rich) or children (plain) instead.- Bare numeric strings for padding. Use
"0px", not"0". - Forgetting the wrapper. A bare
<Row>without an<Email>/<Page>/<Document>/<Body>ancestor has no rendering mode set. <UnlayerProvider>without a wrapper inside. The provider only delivers config to children when there's a wrapper (<Email>,<Page>,<Document>, or<Body>) underneath it. Components placed inside the provider but outside a wrapper don't see the config.<UnlayerProvider>in a Server Component. The provider is"use client". For SSR, passconfigdirectly to the render function or to<Body>.
Email-Client Constraints
Email clients limit what HTML+CSS will render reliably. The <Email> wrapper papers over the worst offenders, but you'll still run into things like:
- Embedded video doesn't play.
<Video>renders a clickable thumbnail that links to the source, not an inline player. Inline<video>tags are stripped almost everywhere. - Custom fonts behave inconsistently. Outlook on Windows in particular falls back to a system font. Stick to the common font stacks for predictable results.
- Dark-mode rendering varies by client. Apple Mail and Outlook on macOS both apply automatic color inversion that surprises designers. Test both modes if dark mode matters to you.
<style>blocks may be stripped. Inline styles always survive, and Elements uses inline styles for everything that can be inlined. The leftover<style>block (hover effects, media queries) belongs in<head>— that's where Gmail, Yahoo, and most webmail clients actually keep it. UserenderToHtmlPartsto split head from body instead of dumping the whole document into<body>.