资讯动态

MJML 入门指南:从 `mj-body`、`mj-section` 到 `mj-column` 理解响应式邮件网格布局

发布时间:2026/9/21 15:46:34 来源:尧图企业网站定制
MJML 入门指南从mj-body、mj-section到mj-column理解响应式邮件网格布局【免费下载链接】mjmlMJML: the only framework that makes responsive email easy项目地址: https://gitcode.com/gh_mirrors/mj/mjml导读本文以 MJML 官方入门文档doc/getting_started.md为骨架系统讲解响应式邮件的基础网格模型——mj-body邮件内容容器、mj-section水平区块与mj-column响应式列三者如何层层嵌套、协同工作并深入剖析自动/手动列宽分配与gutter间距的实现原理。读完本文你将掌握 MJML 中最核心的版式骨架编写能力任意邮件都能用一个 body、若干 section、每个 section 内若干 column的思维拆解成标准网格并能精确控制每列宽度与列间间距。一、为什么 MJML 把邮件拆成网格一封响应式邮件responsive email在外观上可能千差万别但从结构上看它和一个普通的 HTML 模板一样可以被拆解成许多部分放入一个网格grid系统中对齐。MJML 的核心设计思想正是用语义化标签描述网格把表格嵌套、媒体查询、邮件客户端兼容等复杂细节全部交给编译引擎详见 doc/guide.md 的 Overview 描述。这个网格体系由三个层级构成从上到下依次为标签职责对应源码mj-body整封邮件的文档体包含全部内容并定义全局容器宽度packages/mjml-body/src/index.jsmj-section水平方向的一个区块section负责纵向切分邮件packages/mjml-section/src/index.jsmj-column区块内的列column横向切分区块是响应式的核心packages/mjml-column/src/index.js最基本的骨架如下mjml mj-body mj-section mj-column !-- 该列内的内容组件如 mj-text、mj-image、mj-button -- /mj-column /mj-section /mj-body /mjml可以这样理解三层关系mj-body是画布mj-section把画布纵向分成一行一行的横条mj-column再把每个横条横向切成一格一格的单元格——任何 MJML 内容组件最终都必须放进mj-column中这是 MJML 版式的基本约束。二、mj-body整封邮件的容器mj-body标签代表邮件的正文body包含整封文档的所有内容。它既是一个逻辑容器也直接决定了整封邮件的版式基准宽度。在源码中mj-body组件声明了三个可配置属性packages/mjml-body/src/index.js#L7-L11属性类型默认值说明widthunit(px)600px邮件内容区的总宽度只接受像素单位background-colorcolor无邮件正文的背景色idstring无输出到body标签的 id其中width直接决定了下文所有百分比列宽换算的基准。它的默认值是600px见 packages/mjml-body/src/index.js#L13-L15这也是邮件行业最主流的阅读宽度。在渲染时mj-body会把自身的width作为containerWidth传递给所有子组件packages/mjml-body/src/index.js#L17-L22因此修改mj-body的width会等比影响所有以百分比定义宽度的列mjml mj-body width640px mj-section mj-column !-- 此时容器基准宽度为 640px -- /mj-column /mj-section /mj-body /mjml三、mj-section定义水平区块在mj-body内部你首先用mj-section定义邮件中的各个区块。一封典型的营销邮件通常由多个mj-section纵向堆叠组成例如公司头部Company Header、图片头部Image Header、介绍文字、双列内容区、图标区、社交图标区等。mj-section本身承担以下职责见 packages/mjml-section/src/index.js容纳列一个mj-section内可以声明一个或多个mj-column统一背景支持background-color、background-url、background-repeat、background-size、background-position等属性可让整个区块铺上纯色或背景图packages/mjml-section/src/index.js#L9-L33统一内边距默认padding为20px 0上下 20px、左右 0也可分别用padding-top/bottom/left/right覆盖向外传递版式上下文mj-section通过getChildContext()把containerWidth、gutter、direction等值下发给所有列packages/mjml-section/src/index.js#L45-L55这是后续列宽与间距计算的数据来源。简单示例mjml mj-body mj-section background-color#f0f0f0 mj-column !-- 区块内容 -- /mj-column /mj-section /mj-body /mjml四、mj-column响应式的关键官方文档强调Inside any section, there should be columns (even if you need only one column).Columns are what makes MJML responsive.任何 section 内都应放列即使你只需要一列。列是 MJML 响应式的关键。4.1 自动宽度分配Auto sizingMJML 翻译引擎的默认行为是把 section 的空间默认 600px可通过mj-body的width修改按照你声明的列数平均分配。例如下面的布局声明了 2 个列引擎就会生成一个每列占 50% 总宽各 300px的布局mjml mj-body mj-section mj-column !-- First column content -- /mj-column mj-column !-- Second column content -- /mj-column /mj-section /mj-body /mjml依此类推加第三列降到 33%加第四列降到 25%。这个等分逻辑在源码中非常直观mj-column在未显式声明width时以parseFloat(parentWidth) / nonRawSiblings父容器宽度 ÷ 非 raw 兄弟节点数量作为自己的宽度packages/mjml-column/src/index.js#L48-L50。重要提示任何放进mj-column的 MJML 组件如mj-text、mj-image、mj-button其宽度都会自动等同于所在列的 100% 宽度。也就是说列宽定了列内组件的可用宽度也就定了无需也不建议为每个组件单独设置与列宽相关的宽度。4.2 手动宽度设置Manual sizing你也可以用mj-column的width属性手动指定列宽单位支持像素px或百分比%。例如mjml mj-body mj-section mj-column width200px !-- First column content -- /mj-column mj-column width400px !-- Second column content -- /mj-column /mj-section /mj-body /mjml上面的布局中左列固定 200px右列固定 400px合计正好 600px。width的合法值由unit(px,%)类型约束packages/mjml-column/src/index.js#L30底层由 packages/mjml-core/src/helpers/widthParser.js 解析它会从宽度字符串中提取单位px或%百分数在计算时保留小数精度parseFloat像素则取整。需要特别说明的是无论手动还是自动分配最终输出的都是配合媒体查询的百分比类名如mj-column-per-50、mj-column-per-33-333333、mj-column-px-200由 packages/mjml-core/src/helpers/mediaQueries.js 统一生成media only screen and (min-width: breakpoint)样式块桌面端按设定宽度并排显示移动端低于断点自动堆叠为 100% 宽度——这正是响应式的来源。4.3 列的更多可选属性除宽度外mj-column还支持一系列用于精修外观的属性packages/mjml-column/src/index.js#L8-L31属性类型说明background-colorcolor列的背景色padding/padding-top/bottom/left/rightunit(px,%)列的内边距会从列宽中扣除border/border-top/bottom/left/rightstring列的外边框border-radiusstring列的外圆角开启后自动使用border-collapse: separateinner-border/inner-border-radiusstring列内层表格的边框与圆角常用于实现边框嵌套效果见 packages/mjml/test/column-border-radius.test.jsvertical-alignenum(top,bottom,middle)列内容的垂直对齐默认topdirectionenum(ltr,rtl)列内文字的书写方向五、Section gutter列与列之间的一致间距当你在一个mj-section内放多个列时列与列之间默认是紧贴的。要添加一致的间距可以在mj-section上设置gutter属性。gutter 声明在 section 上并作用于它的所有列packages/mjml-section/src/index.js#L25支持px与%两种单位。mjml mj-body mj-section gutter4% mj-column !-- First column content -- /mj-column mj-column !-- Second column content -- /mj-column /mj-section /mj-body /mjml上面的布局中两个列之间会出现 4% 的间距。当邮件在移动端堆叠成单列时这个 gutter 会自动转换为列与列之间的垂直间距下文的移动端行为会详细说明。5.1 gutter 的自动扣除机制理解 gutter 最关键的规则是gutter 会自动从你在mj-column上声明的宽度中扣除你不需要自己手工计算列宽。举个例子声明4%的 gutter并放置两个宽度各为50%的mj-column那么实际渲染出的每列宽度将是48%两列之间各让出2%合计 4%作为 gutter 间距。这段声明 50% 4% gutter → 实际 48% 列宽 2% 双边距的换算在源码中有完整实现packages/mjml-column/src/index.js#L267-L298reduction gutter × (sibling - 1) / sibling reducedWidth max(0, parsedWidth - reduction)同时gutter 间距被拆成首列只加右侧、末列只加左侧、中间列两侧各一半的 paddingpackages/mjml-column/src/index.js#L341-L379最终以mj-column-gutter-{sibling}-{index}-{unit}-{value}这类类名 媒体查询规则输出。这一行为有专门的测试用例验证packages/mjml/test/section-gutter.test.js#L4-L29// 输入mj-section gutter4% 两列无宽度 // 断言 // .mj-column-per-48 { width:48% !important; max-width: 48%; } // .mj-column-gutter-2-1-per-4 { padding: 0% 2% 0% 0% !important; } // .mj-column-gutter-2-2-per-4 { padding: 0% 0% 0% 2% !important; }5.2 gutter 的移动端行为当多个列在移动端堆叠为单列时gutter 会自动转为列与列之间的垂直间距——也就是说桌面端横向的列间距在移动端变成了堆叠列之间的纵向留白且不会在左右外边缘产生多余的边距packages/mjml-column/src/index.js#L381-L394。对于放在mj-grouppackages/mjml-group/src/index.js中的列行为略有不同group 内的列在移动端不会堆叠因此 gutter 会保持桌面端的水平 padding 形式内联输出避免重复的媒体查询规则见 packages/mjml/test/section-gutter.test.js#L68-L95。5.3 用 padding 处理边缘间距gutter 只负责列与列之间的间距列组与 section 左右边缘之间的间距需要借助mj-section的padding属性。padding默认值为20px 0即上下 20px、左右 0。你可以这样为左右边缘留白mjml mj-body mj-section gutter4% padding0 24px mj-column !-- First column content -- /mj-column mj-column !-- Second column content -- /mj-column /mj-section /mj-body /mjml实际使用时也可以把 gutter 与百分比 padding 组合例如padding4%gutter4%section 内边距与列间距各司其职、互不干扰该组合在 packages/mjml/test/section-gutter.test.js 的多组测试中均有覆盖。六、从入门到实战一个完整的双列 gutter 示例综合以上内容把官方文档中的零散示例组装成一封可实际编译的最小邮件mjml mj-body width600px background-color#f6f6f6 mj-section background-color#ffffff padding20px gutter4% mj-column width50% vertical-alignmiddle mj-text font-size16px color#333333 左侧内容一段介绍文字宽度自动铺满所在列。 /mj-text /mj-column mj-column width50% vertical-alignmiddle mj-image width200px srchttps://example.com/your-image.png alt右侧图片 /mj-image /mj-column /mj-section /mj-body /mjml用 CLI 编译README.md 中提供了完整命令说明mjml input.mjml -o output.html或在 Node.js 中调用packages/mjml/src/index.jsimport mjml2html from mjml const { html, errors } await mjml2html( mjml mj-body mj-section gutter4% mj-columnmj-textLeft/mj-text/mj-column mj-columnmj-textRight/mj-text/mj-column /mj-section /mj-body /mjml ) console.log(html) if (errors.length) console.error(errors)七、源码级验证列宽与 gutter 是怎么算出来的为了让自动等分 gutter 自动扣除不只停留在文档描述层面这里梳理一下底层计算链路均可在仓库中直接核对mj-body设定基准width默认600px通过getChildContext()注入containerWidthpackages/mjml-body/src/index.js#L17-L22。mj-section传递 guttermj-section把自身的gutter、direction与containerWidth一并下发给子列packages/mjml-section/src/index.js#L45-L55。mj-column计算实际列宽未声明width时按父宽 / 非 raw 兄弟数等分声明后先解析单位packages/mjml-core/src/helpers/widthParser.js再扣除自身padding、border、inner-border与 gutter 分摊值packages/mjml-column/src/index.js#L38-L68。媒体查询落地所有列宽与 gutter padding 类名被收集进mediaQueries最终由 packages/mjml-core/src/helpers/mediaQueries.js 生成media only screen and (min-width: breakpoint)样式块实现桌面并排、移动堆叠的响应式效果。测试兜底仓库中 packages/mjml/test/section-gutter.test.js 覆盖了百分比/像素 gutter、混合单位、奇数像素取整平衡如 3 列 200px 4% gutter 会输出 185px/184px 以保持总宽一致、RTL 方向等多种场景可作为理解引擎行为的活文档。八、小结至此MJML 入门阶段最核心的版式知识已经齐备mj-body是邮件的画布与宽度基准默认 600pxmj-section是纵向堆叠的水平区块负责分区与统一背景/内边距mj-column是横向切分的响应式列自动等分或手动指定宽度gutter在 section 上声明、作用于所有列自动从列宽中扣除并转换为移动端的垂直间距padding负责处理列组与 section 边缘的留白。掌握body → section → column这一层骨架之后就可以放心地往列里填充mj-text、mj-image、mj-button、mj-divider、mj-social等标准组件完整组件清单可参考 doc/components_1.md 与 doc/components_2.md并将它们组合成一封结构清晰、跨客户端稳定的响应式邮件。【免费下载链接】mjmlMJML: the only framework that makes responsive email easy项目地址: https://gitcode.com/gh_mirrors/mj/mjml创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价