关于 email-html-mjml
email-html-mjml 是用于编写 MJML 5.x 响应式邮件模板并编译为 HTML 的技能。它侧重跨邮件客户端兼容、严格验证与无障碍要求,并要求交付源文件和编译文件。
主要功能
- 01生成 MJML 5.x 模板
- 02编译并验证 HTML
- 03提供 Outlook 和 Gmail 兼容指导
- 04检查无障碍与深色模式
- 05查阅 MJML 组件参考
适用场景
- 01制作事务类邮件模板
- 02创建促销邮件版式
- 03准备响应式新闻邮件
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ framix-team/ skill-email-html-mjml --skill email-html-mjml安装后在 Claude Code 中输入/email-html-mjml确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
compilation.mdLICENSEmjml-reference.mdassets/examples/basic-layout.mjmlnewsletter.mjmlorder-confirmation.mjmlpromo-sale.mjmlassets/examples/partials/footer.mjmlcomponents/advanced.mdcontent.mdhead.mdinteractive.mdlayout.md详细介绍
email-html-mjml — 响应式邮件开发者
生成有效、兼容不同邮件客户端的 MJML 5.x 模板,并将其编译为可用于生产环境的 HTML。首要目标是兼容性:Outlook(2013–365)、Gmail(网页端/应用)、Apple Mail 和主流移动端客户端。所有输出都必须通过 --config.validationLevel=strict 编译,并能经受 Gmail 的 102KB 截断限制。
工作流程
- 收集需求 — 根据用户消息和对话上下文推断邮件类型、品牌颜色和内容。仅在确实缺少且会阻碍进展的信息时提问(例如未提供颜色,但布局中有品牌区块)。切勿一开始就罗列问题。
- 规划布局 — 编写代码前决定并说明结构(单栏、双栏网格、主视觉区 + 内容等)。
- 加载组件参考 — 编写任何 MJML 前,先阅读下方组件索引中的相关文件
- 生成 MJML — 从
<mjml>开始编写完整、有效的 MJML,并包含完整的<mj-head> - 编译 — 遵循
compilation.md。使用--config.minify=true运行npx mjml - 交付两个文件 — 始终输出
.mjml源文件和编译后的.html文件
9 条工程规则
- 结构完整性 — 所有视觉内容都必须位于
<mj-section>内的<mj-column>中。Section 不能嵌套。 - 响应式默认值 — 默认宽度为 600px。对于并排元素(社交栏、Logo 行),使用
<mj-group>防止在移动端堆叠。使用<mj-section gutter="...">设置列间距,而不是通过 padding 实现。 - Outlook 兼容性 — 使用
<mj-font>设置 Web 字体(防止回退到 Times New Roman)。始终提供回退字体栈(Arial, sans-serif)。对于带背景图片的<mj-section>,始终同时设置background-size和回退用的background-color。 - Gmail 优化 — 自定义 CSS 使用
<mj-style>上的inline="inline"。关键样式优先使用组件属性(color、font-size),而不是 CSS 类。 - 深色模式 — 仅在用户明确要求,或邮件使用浅色背景、强制反转会造成刺眼效果时,加入深色模式支持。参见下方深色模式模式。
- 无障碍访问 — 每个
<mj-image>都必须设置alt。始终设置<mj-title>(用于填充aria-label)。保持 WCAG 2.1 AA 对比度达到 4.5:1。对于标题角色,使用mj-html-attributes——在严格验证下,直接在mj-text上设置role/aria-level属性不合法(参见下方无障碍检查清单)。 - 样式效率 — 使用
<mj-attributes>中的<mj-all>、组件默认值和<mj-class>,消除重复的内联样式。 - 主视觉区 — 全宽主视觉横幅使用
<mj-hero>;在不支持的客户端中,它会回退为普通 section。避免使用<mj-accordion>和<mj-carousel>——客户端支持太差,实用性不高。 - 模板支持 — 普通插值(
{{firstName}})无需包装——它们会原样保留在文本、属性、mj-title和mj-preview中。只有包含<或>的块标签({% if x < 5 %}、{{#if a<b}})才需要 `` 保护,否则压缩会静默破坏它们。在列中,内容组件之间的<mj-raw>会将其内容输出到</tr>和<tr>之间,导致标记无效;应将mj-raw放在 section 之间,并避免在<mj-style>中放置模板标签(参见compilation.md)。
关键注意事项
MJML 5 默认禁用 mj-include:
- 除非显式启用 include,否则
<mj-include>标签会被静默忽略——这是相较于 MJML 4 有意进行的安全更改 - CLI:添加
--config.allowIncludes true。Node API:传入ignoreIncludes: false - 使用
--config.includePath(CLI)或includePath(Node)限定允许的目录——仅支持 MJML、HTML 和 CSS include - 除非目录已加入允许列表,否则不允许包含位于模板自身目录之外的局部文件
--config.validationLevel=strict无法检测到此问题——被丢弃的 include 仍会以0退出,且仍会写入.html。编译成功并不代表 include 已生效;交付前,请在输出中搜索已知局部文件内容- 如果编译后的模板缺少你预期由 include 引入的内容,请先检查这一点
Outlook:
- 背景图片:仅为
<mj-section>和<mj-hero>生成 VML——其他位置均不会生成 - 背景定位:仅支持关键字值(
top、center、bottom)——像素值会被忽略 background-repeat="no-repeat"始终应与显式设置的background-size配对- 字体回退:
<mj-font>会通过 MSO 条件注释对 Outlook 隐藏@font-face
Gmail:
- 关键布局请使用组件属性——CSS 类可能会被移除
- 102 KB 截断限制:始终使用
--config.minify=true编译
iOS / Android 堆叠:
- MJML 5 的压缩不再移除标签之间的空白字符——
htmlnano会将连续空白字符折叠为一个空格,而html-minifier会将其移除(已验证:v4 输出<![endif]--><div class="mj-column-per-50",v5 输出<![endif]--> <div ...)。仍然有效的防堆叠措施是 MJML 添加到父级<td>上的font-size:0px,两个版本都会输出此属性 - 要恢复 v4 的空白字符移除行为:
--config.minifyOptions '{"collapseWhitespace":"all"}'(必须使用 JSON 字符串格式) - 标签之间的空白字符即使在
<mj-group>内也会导致堆叠
垂直对齐问题:
- 如果某个区段中的任何列设置了
vertical-align,该区段中的所有列都必须显式设置此属性
JavaScript:
- 所有邮件客户端(Gmail、Outlook、Apple Mail、iOS Mail)都会完全阻止 JS。不能使用
onclick、剪贴板 API,也不能实现任何交互功能。看似可交互的元素(复制按钮、切换控件)都只是装饰。
深色模式模式
<mj-head>
<mj-raw>
<meta name="color-scheme" content="light dark">
<meta name="supported-color-schemes" content="light dark">
</mj-raw>
<mj-style inline="inline">
.dark-logo { display: none !important; }
</mj-style>
<mj-style>
@media (prefers-color-scheme: dark) {
.light-logo { display: none !important; }
.dark-logo { display: block !important; }
}
</mj-style>
</mj-head>
安全的中性色:#121212(而非 #000000)和 #F1F1F1(而非 #FFFFFF)——可避免刺眼的强制反转效果。
无障碍检查清单
- 已设置
<mj-title>(作为屏幕阅读器的邮件标签和aria-label) - 在根
<mjml>标签上设置lang属性 - 每个
<mj-image>和<mj-social-element>都设置了alt - 通过
mj-html-attributes设置标题角色(不要将其作为mj-text的直接属性):<mj-html-attributes> <mj-selector path=".email-heading div"> <mj-html-attribute name="role">heading</mj-html-attribute> <mj-html-attribute name="aria-level">1</mj-html-attribute> </mj-selector> </mj-html-attributes> <mj-text css-class="email-heading" ...>Heading text</mj-text> - 所有文本与背景组合的对比度均达到 4.5:1
- 不要将文字嵌入图片——始终使用实时的
<mj-text>块
组件索引
编写任何 MJML 之前,请先阅读你将使用的组件对应的文件。
| 分组 | 组件 | 何时加载 | 文件 |
|---|---|---|---|
| Head | mj-attributes, mj-font, mj-style, mj-preview, mj-breakpoint, mj-html-attributes | 设置 head、全局样式时 | components/head.md |
| 布局 | mj-body, mj-section, mj-column, mj-group, mj-wrapper | 构建结构 / 网格时 | components/layout.md |
| 内容 | mj-text, mj-image, mj-button, mj-divider, mj-spacer, mj-table | 添加内容块时 | components/content.md |
| 交互 | mj-accordion, mj-carousel, mj-social, mj-navbar | 添加交互或社交元素时 | components/interactive.md |
| 高级 | mj-hero, mj-raw, mj-include | 添加主视觉横幅、模板标签、局部文件时 | components/advanced.md |
通用参考(层级结构、结束标签、验证、宽度计算、Gmail 截断限制):mjml-reference.md
编译
完整工作流请阅读 compilation.md。关键命令:
npx mjml template.mjml -o dist/template.html --config.minify=true --config.validationLevel=strict
硬性规则:
- 切勿运行
npm install -g mjml - 始终使用
npx或./node_modules/.bin/mjml - 如果
package.json中没有 mjml,请建议运行npm install -D mjml
示例
在 MJML 5.4.0 上,以下四个示例均可在 --config.validationLevel=strict --config.minify=true 下成功编译。
| 文件 | 参考用途 |
|---|---|
assets/examples/basic-layout.mjml | 仅供参考结构。MJML 文档中的示例:包含 6 个区块的布局(页眉、图片主视觉 + 按钮、简介、双列图片 + 文本、三列图标、社交媒体行)。刻意保持精简——没有 mj-head、深色模式或实际文案,只有占位文案。不是生产模板。 |
assets/examples/order-confirmation.mjml | 交易类邮件。完整的 mj-head(mj-attributes + mj-class + mj-font + mj-html-attributes)、带有 scope="col" 表头的收据 mj-table、在 mj-raw 中使用 Handlebars 并配有 htmlmin:ignore、条件区块,以及通过 mj-include 引入 partials/footer.mjml。需要 --config.allowIncludes true。 |
assets/examples/promo-sale.mjml | 促销类邮件。mj-hero 和 mj-section 背景图片(生成 VML)、mj-navbar、不会堆叠的 mj-group 行、mj-social、mj-breakpoint,以及 MJML 5 的 gutter / border / inner-padding 属性。 |
assets/examples/newsletter.mjml | 编辑类邮件 + 深色模式。采用上文完整的深色模式模式、mj-wrapper、用于 aria-level 1 和 2 的 mj-html-attributes,并为每个区块中的每一列设置 vertical-align。 |
这些文件中的所有文案、图片 URL 和品牌都是占位内容——请替换,不要原样发布。
输出
始终交付:
<name>.mjml— 完整的 MJML 源码(可编辑、可纳入版本控制)<name>.html— 编译后的输出(可用于生产环境,通过 ESP 发送)
文件名应根据邮件类型命名:welcome.mjml、promo-sale.mjml、order-confirmation.mjml