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

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

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

MJML在现示例查看:Email Editor

一、效果展示及完整代码

1.1. 效果展示

PC端(宽度600px)

移动端(宽度400px)

1.2. 完整代码

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

ini 复制代码
<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时两列显示

通过配置如下代码:

xml 复制代码
<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>
相关推荐
AAA不会前端开发2 小时前
TypeScript核心类型系统完全指南
前端·typescript
徐同保2 小时前
使用GitKraken把feature_xtb_1104分支的多次提交记录合并到一起,只保留一次提交记录,并合并到master分支
前端
小光学长2 小时前
基于Vue的智慧楼宇报修平台设计与实现066z15wb(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
前端·数据库·vue.js
醉方休2 小时前
web前端 DSL转换技术
前端
sen_shan2 小时前
Vue3+Vite+TypeScript+Element Plus开发-27.表格页码自定义
前端·javascript·typescript
刺客_Andy2 小时前
React 第五十二节 Router中 useResolvedPath使用详解和注意事项示例
前端·react.js·架构
豆浆9452 小时前
vue3+qiankun主应用和微应用的路由跳转返回
前端
王将近2 小时前
Cesium 山洪流体模拟
前端·cesium
小时前端3 小时前
当循环遇上异步:如何避免 JavaScript 中最常见的性能陷阱?
前端·javascript