普通视图

发现新文章,点击刷新页面。
昨天以前首页

MJML邮件如何随宽度变化动态切换有几列📮

2025年11月7日 18:36

需求:邮件中需要展示数组信息,每个模块宽高固定不变,在PC端(600px)三列展示在移动端(400px)两列展示,且该mjml格式邮件样式在GMail中可以正常显示。

MJML官方文档:MJML - The Responsive Email Framework

MJML在现示例查看:Email Editor

一、效果展示及完整代码

1.1. 效果展示

PC端(宽度600px)

移动端(宽度400px)

1.2. 完整代码

注:下列代码请在支持解析MJML文件的项目下运行查看


<mjml>
  <mj-head>
    <mj-style inline="inline">
      .card-content {
        width: 100%;
        text-align: left;
        font-size:0;
        background: red;
      }
      .fixed-item {
        display: inline-block !important;
        width: 180px !important;
        height: 100px !important;
        margin: 10px !important;
        color: #000;
        font-size: 14px;
        line-height: 100px;
        background: #f0f0f0 !important;
        text-align: center !important;
        vertical-align: top !important;
      }
      .item-image {
        float: left;
        width: 42%;
        height: 100%;
      }
      .item-image img {
        width: 100%;
      }
      .item-details {
        float: left;
        width: 58%;
        height: 100%;
        font-family: PingFang SC;
        text-align: left;
      }
      .item-details-text-title {
        margin: 15px 10px 5px 10px;
        height: 24px;
        line-height: 24px;
        font-size: 18px;
        font-weight: 600;
        color: #13171D;
      }
      .item-details-text-subtitle {
        margin: 0 10px;
        height: 24px;
        line-height: 24px;
        font-size: 14px;
        color: #6d6d6d;
      }
    </mj-style>
  </mj-head>
  <mj-body>
    <mj-section>
      <mj-column>
        <mj-raw>
          <div class="card-content">
            <!-- 固定宽高元素会自动换行 -->
            <div class="fixed-item">
              <div class="item-image">
                <img src="https://gips0.baidu.com/it/u=3602773692,1512483864&fm=3028&app=3028&f=JPEG&fmt=auto?w=960&h=1280" />
              </div>
              <div class="item-details">
                <div class="item-details-text-title">名字1</div>
                <div class="item-details-text-subtitle">这是一段描述文字「1」</div>
              </div>
            </div>
            <div class="fixed-item">
              <div class="item-image">
                <img src="https://gips0.baidu.com/it/u=3602773692,1512483864&fm=3028&app=3028&f=JPEG&fmt=auto?w=960&h=1280" />
              </div>
              <div class="item-details">
                <div class="item-details-text-title">名字2</div>
                <div class="item-details-text-subtitle">这是一段描述文字「2」</div>
              </div>
            </div><div class="fixed-item">
              <div class="item-image">
                <img src="https://gips0.baidu.com/it/u=3602773692,1512483864&fm=3028&app=3028&f=JPEG&fmt=auto?w=960&h=1280" />
              </div>
              <div class="item-details">
                <div class="item-details-text-title">名字3</div>
                <div class="item-details-text-subtitle">这是一段描述文字「3」</div>
              </div>
            </div><div class="fixed-item">
              <div class="item-image">
                <img src="https://gips0.baidu.com/it/u=3602773692,1512483864&fm=3028&app=3028&f=JPEG&fmt=auto?w=960&h=1280" />
              </div>
              <div class="item-details">
                <div class="item-details-text-title">名字4</div>
                <div class="item-details-text-subtitle">这是一段描述文字「4」</div>
              </div>
            </div><div class="fixed-item">
              <div class="item-image">
                <img src="https://gips0.baidu.com/it/u=3602773692,1512483864&fm=3028&app=3028&f=JPEG&fmt=auto?w=960&h=1280" />
              </div>
              <div class="item-details">
                <div class="item-details-text-title">名字5</div>
                <div class="item-details-text-subtitle">这是一段描述文字「5」</div>
              </div>
            </div><div class="fixed-item">
              <div class="item-image">
                <img src="https://gips0.baidu.com/it/u=3602773692,1512483864&fm=3028&app=3028&f=JPEG&fmt=auto?w=960&h=1280" />
              </div>
              <div class="item-details">
                <div class="item-details-text-title">名字6</div>
                <div class="item-details-text-subtitle">这是一段描述文字「6」</div>
              </div>
            </div><div class="fixed-item">
              <div class="item-image">
                <img src="https://gips0.baidu.com/it/u=3602773692,1512483864&fm=3028&app=3028&f=JPEG&fmt=auto?w=960&h=1280" />
              </div>
              <div class="item-details">
                <div class="item-details-text-title">名字7</div>
                <div class="item-details-text-subtitle">这是一段描述文字「7」</div>
              </div>
            </div><div class="fixed-item">
              <div class="item-image">
                <img src="https://gips0.baidu.com/it/u=3602773692,1512483864&fm=3028&app=3028&f=JPEG&fmt=auto?w=960&h=1280" />
              </div>
              <div class="item-details">
                <div class="item-details-text-title">名字8</div>
                <div class="item-details-text-subtitle">这是一段描述文字「8」</div>
              </div>
            </div>
          </div>
        </mj-raw>
      </mj-column>
    </mj-section>
  </mj-body>
</mjml>

二、实现方法及逻辑解析

需求整理:

  • PC端(宽度600px)下三列显示,移动端(400px)下两列展示
  • 数组的每个元素宽高固定不变,不会随着宽高变化而比例性 压缩/拉伸
  • GMail中样式内容正常显示
  • MJML中不支持javascrip逻辑,MJML智能单纯的显示同步显示的值

方法调研

方法一( ❌ 不可行)

基于以上需求调研发现GMail不支持CSS3样式语法,这样下来display:flexdisplay:girdposition等诸多样式均不可使用

方法二( ❌ 不可行)

MJML中不支持写入javascrip逻辑,所以试用javascrip 操控/监听 DOM的方法是行不通的

方法三( ❌ 不可行)

MJML标签中有一个<mj-fixed-column width="33.3%">可以设置一行有几列,最后将<mj-fixed-column width="33.3%">标签包裹在<mj-section padding="0">

    1. 但是因为不能使用javascrip语言来监听尺寸变化,所以不能动态切换<mj-fixed-column>标签中width何时为 50% 何时为 33.3%
    2. 所以通过网络上查询发现可以考虑使用@media screen and (max-width: 480px),来实现屏幕尺寸变化时,来通过class样式来改变元素宽度
    3. 但是配置后发现MJML不能识别 或 运行@media screen and (max-width: 480px)这种代码,类似于MJML不能运行javascrip一样
方法四( ✅ 可行)

故基于以上,思路需要调整为如何让数组元素在GMail支持的样式配置中,跟随宽度变化自动换行,这样使得宽度为600px时三列显示,在宽度为400px时两列显示

通过配置如下代码:


<mjml>
  <mj-head>
    <mj-style inline="inline">
      .fixed-item {
        display: inline-block !important;
        width: 100px !important;
        height: 100px !important;
        margin: 10px !important;
        background: #f0f0f0 !important;
        text-align: center !important;
        vertical-align: top !important;
      }
    </mj-style>
  </mj-head>
  <mj-body>
    <mj-section>
      <mj-column>
        <mj-raw>
          <div style="text-align: left; font-size: 0;">
            <!-- 固定宽高元素会自动换行 -->
            <div class="fixed-item">项目1</div>
            <div class="fixed-item">项目2</div>
            <div class="fixed-item">项目3</div>
            <div class="fixed-item">项目4</div>
            <div class="fixed-item">项目5</div>
            <div class="fixed-item">项目6</div>
            <div class="fixed-item">项目7</div>
            <div class="fixed-item">项目8</div>
          </div>
        </mj-raw>
      </mj-column>
    </mj-section>
  </mj-body>
</mjml>
❌
❌