Hyper Elements vs MJML
Both write responsive emails that work in Outlook. Hyper Elements does it in React and TypeScript, checks every email, shows it in every email client, and renders it on-brand.
Hyper Elements vs MJML at a glance
What you get with each, side by side, if you’re weighing an MJML alternative.
Included free
See it in Outlook, Gmail, Apple Mail and Yahoo Mail before you send
MJML shows your email in a browser at different widths. Hyper Elements shows you what Outlook, Gmail and Apple Mail do with it.
- FreeNo account, key or limit
- LocalNothing sent or uploaded
- Light and darkDesktop and phones
- FastAs long as a render



- Classic Outlook97%
- Outlook.com99%
- Outlook for Mac98%
- Gmail99%
- Gmail app98%
- Apple Mail98%
- Yahoo Mail99%
- AOL Mail99%
Before you send
Every email checked, in code and in CI
Each render lists what classic Outlook, Gmail and the other clients will change, and a mistake stops it with what to write instead.
- In your coderender() and validate() return them, with where each one is
- In CIThe CLI's check exits 1 on an error, with --json for scripts
- With the fixEach one says what to write instead, so an agent fixes it itself
MJML's validator checks its own tags and attributes, not what email clients will change.
How diagnostics work →- error
style/unknown"marginBottom" isn't a style a Text takes: use the parent's gap, or padding. - info
email/outlook-degradedborderRadius on this Column in classic Outlook: square corners - info
email/degradedhover on this Button in some email clients: no change (where it shows, keyboard focus gets it too) - info
email/outlook-degradedletterSpacing on this Text in classic Outlook: normal spacing: Word keeps letter spacing but doesn't draw it
On brand, in every email
Write your brand once as a theme. The template names no colors or fonts; swap the theme and the same email is someone else's.

theme={north}North
theme={bloom}Bloom<Email theme={north}>
<Column style={{ apply: ["card"] }}>
<Heading level={1}>The winter collection…</Heading>
<Text>Everything you asked for…</Text>
<Button href="…">Shop the drop</Button>
<Button href="…" variant="secondary">
See the lookbook
</Button>
</Column>
</Email>- TokensColors, fonts, sizes, spacing and corners, checked when the template is read
- Defaults and variantsEvery Button, Heading and Divider styled once, with named versions
- EverywhereThe same theme brands emails, pages, PDFs and images
MJML: defaults per component with mj-attributes and named groups with mj-class, with no tokens.
How themes work →The same email in MJML and Hyper Elements
MJML has no variables: {{name}} is left for a templating language. In Hyper Elements it's a typed prop.
Hyper Elements 33s1,831 tokens
import { Button, Column, Email, Heading, Section, Text } from "@hyper-elements/react";
export default function Welcome({ name }: { name: string }) {
return (
<Email
width={520}
previewText="Welcome to Orbit"
style={{ backgroundColor: "#f3f4f6", fontFamily: "Helvetica, Arial, sans-serif" }}
>
<Section style={{ padding: [40, 0] }}>
<Column style={{ backgroundColor: "#ffffff", borderRadius: 8, padding: 32, gap: 16 }}>
<Heading style={{ fontSize: 24, color: "#101828" }}>
Welcome, {name}
</Heading>
<Text style={{ fontSize: 16, color: "#4a5565" }}>
Your workspace is ready.
</Text>
<Button
href="https://example.com/start"
style={{ backgroundColor: "#4f39f6", borderRadius: 6 }}
>
Open your workspace
</Button>
</Column>
</Section>
</Email>
);
}MJML 43s2,762 tokens
<mjml>
<mj-head>
<mj-preview>Welcome to Orbit</mj-preview>
<mj-attributes>
<mj-all font-family="Helvetica, Arial, sans-serif" />
</mj-attributes>
</mj-head>
<mj-body width="520px" background-color="#f3f4f6">
<mj-section padding="40px 0">
<mj-column background-color="#ffffff" border-radius="8px" padding="32px">
<mj-text font-size="24px" font-weight="700" color="#101828" padding="0 0 16px">
Welcome, {{name}}
</mj-text>
<mj-text font-size="16px" color="#4a5565" padding="0 0 16px">
Your workspace is ready.
</mj-text>
<mj-button href="https://example.com/start" background-color="#4f39f6" border-radius="6px" align="left" padding="0">
Open your workspace
</mj-button>
</mj-column>
</mj-section>
</mj-body>
</mjml>Beyond email
Change a template's root and the same content becomes a web page, a PDF or an image.
Questions about switching from MJML
What are the alternatives to MJML?
The main ones are Hyper Elements, React Email and Maizzle. Hyper Elements and React Email write emails as React components; Hyper Elements also works out the layout, checks the email, previews it in email clients, keeps it on brand with a theme, and renders the same template as a page, a PDF or an image. Maizzle builds HTML emails with Tailwind CSS.
Which handles Outlook better, MJML or Hyper Elements?
Both write the tables and conditional comments classic Outlook needs, so you don't. Hyper Elements also works out every width in px before it writes anything, tells you what classic Outlook will show differently (square corners, say), and previews the email as classic Outlook draws it.
How do I put data in an email?
In Hyper Elements a template is a function: its props are typed, and loops and conditions are plain TypeScript. MJML has no variables, loops or conditions; its docs suggest adding a templating language such as Handlebars or Liquid.
Can I preview my MJML emails in Outlook and Gmail?
Yes, for free. Compile them to HTML and give it to Hyper Elements' email client emulator, @hyper-elements/email-clients, or paste it into the email testing playground. It previews classic Outlook, Outlook.com, Gmail, Apple Mail, Yahoo Mail and more on your machine, in light and dark mode, with no test sends or account.
Can I convert my MJML templates?
Not automatically yet: the migrate command converts React Email and Unlayer Elements templates. Your MJML emails' HTML works with the email client emulator as it is.
Do I need a React app to use Hyper Elements?
No. Templates are React components in TypeScript or JavaScript, but render() runs on your server and returns HTML and plain text, to send with any email provider. Nothing runs in the reader's browser.
Which is faster for a coding agent?
In our benchmark, Claude Code reached a passing email 1.3× faster with Hyper Elements than with MJML, writing 1.5× fewer output tokens, across five briefs and 16 runs each. Both passed the first check every time, and MJML was faster on one of the five emails. It's one agent and one model on short, fully specified emails. The harness is in the repository, so you can run it with your own agent.
Start with Hyper Elements
Install the package and write your first email, or keep your MJML emails and preview their HTML in every client for free.
Also compare: Hyper Elements vs React Email · React Email alternatives · MJML alternatives · Litmus alternatives


