做了这个活动,感觉自己成了垂直排版大师

2,857 阅读7分钟

本文作者:阅文前端团队

原创声明:本文为阅文前端团队 YFE 成员出品,请尊重原创,转载请联系公众号 (id: yuewen_YFE) 获取授权,并注明作者、出处和链接。

全文及图片内的数字信息均非真实,仅供技术展示参考~

前段时间协助完成作家的盘点活动,设计大大给的视觉稿如下图。最初拿到稿子时,以为是一个简单的常规活动,实际在完成这个活动的过程中有一点点小波折,自己也在这个过程中学习到了关于垂直排版的知识点,下面来跟大家描述做这个活动的心路历程,一起探索垂直排版的奥秘~

image.png

文字竖排🤔,立马想到使用 writing-mode,改变文字展示的行进方向

大家都知道的writing-mode

writing-mode 可以将文档流由水平方向调整为垂直方向

以p标签内的一段文本为例,对其添加 writing-mode: vertical-rl,可以快速实现如下图所示的文字竖排效果

image.png

p标签示例代码如下:

<p class="text-vertical">爱交流,也爱独处</p>

.text-vertical {
  writing-mode: vertical-rl;
}

源码可打开链接

一顿页面基础布局下来,可以看到页面效果和设计稿还是有差异😔,具体如下图的红色框线内;设计稿中红色框线内的数字是“直立向上”展示的

image.png

感觉页面还原的展示也无伤大雅,于是拿着对比图找设计大大沟通;但是设计大大还是比较坚持视觉稿上的数字展示效果,以便更好传达活动内的关键信息(用户不需要旋转手机 or 侧头即可快速看清数据)

image.png

在纠结更好实现方案的时候,去请教了一下张老师,张老师提示可以使用 text-orientation:upright,即使是较差机型,可以优雅降级展示非竖向的效果,不影响活动

向产品咨询了产品用户机型占比,较差机型的占比很低很低,而且产品也接受较低端机型降级的效果,完美💯

image.png

在张老师的指点下,专门去学习了 text-orientation 属性相关内容

部分人知道都text-orientation

text-orientation: upright 可以将垂直排版的(设置了 writing-mode,且值不为 horizontal-tb)内容均直立向上展示

在之前的示例基础上,添加 text-orientation: upright 即可实现将数字直立向上展示,面效果可以看下方图片中红色线框内数字

image.png

p标签示例代码见下方:

<p class="text-vertical">999篇日记,12356万字</p>
.text-vertical {
    writing-mode: vertical-rl;
    text-orientation: upright;
    -webkit-text-orientation: upright;
  }

源码可打开链接

调整完成后,活动大体完成,活动进入测试阶段;活动提测后,测试随口提了一句“这个日期看着有一点点不方便”

image.png

虽然测试只是随口一说,但我就放在了心上,思考有没有可能优化一下这个日期显示呢?念念不忘,必有回响,偶然发现 text-combine-upright 的属性可以解决此类竖排横向合并

较少人知道的text-combine-upright

text-combine-upright,可以横向合并显示 2-4 字符,正好特别适合垂直排版中日期横向显示

下图中红色线框内,就是添加 text-combine-upright: all 后日期横向合并的效果,“10” 被合并到一起展示,更利于读者快速获取文字信息

image.png 示例代码见下方:

<p class="text-vertical">
  <span class="upright-combine">10</span><span class="upright-combine">1</span>日时光日记上线
</p>
.text-vertical {
   writing-mode: vertical-rl;
   text-orientation: upright;
}
.upright-combine {
   /* for IE11+ */
  -ms-text-combine-horizontal: all;
  /* for Chrome/Firefox */
  text-combine-upright: all;
  /* for Safari */
  -webkit-text-combine: horizontal;
}

源码可打开链接 具体操作步骤说明如下:

1)将待合并元素外包裹一层标签

2)添加 text-combine-upright: all

text-combine-upright 属性支持关键字值和数字值,考虑到数字值的兼容性不佳,此处主要是用使用关键字all实现的

3)兼容处理,对 IE 浏览器和 Safari 浏览器做兼容处理(支持 IE11+),说明及代码见下方:

IE 浏览器使用的是 -ms-text-combine-horizontal 属性,与 text-combine-upright 属性一致 Safari 浏览器使用 -webkit-text-combine 属性,仅支持 none 和 horizontal 属性值

项目中实际代码片段为下方所示,可以兼容移动端项目,日期展示优化完成!

.upright-combine {
  /* for IE11+ */
  -ms-text-combine-horizontal: all;
  text-combine-upright: all;
  /* forSafari */
  -webkit-text-combine: horizontal;
}

text-combine-upright 使用注意事项:

  • 只用于 2-4 字符的横向合并,例如日期、年份等
  • 由于数字值的兼容性不佳,需要将待横向合并的内容包裹标签

至此,该活动顺利完成并上线了,在完成改活动的过程并非一蹴而就。关于数字垂直排版的实现方案,中间也实践过一些其他方案,可能会对大家未来实现类似场景有参考价值~

数字垂直排版的其他方案

最初在考虑实现数字垂直排版的时候,实践过其他方案,下面跟大家分享一下~

1.JS分割大法

JS 将所有的文本信息均切割为单个标签,将单个文本内容都作为 block 元素,此时无需设置 writing-mode,直接设置外段落文本的最大宽度为 1em,即可达到内容竖向 + 数字直立向上效果

核心代码如下所示:

function text2html(element) {
  var treeWalker = document.createTreeWalker(element, NodeFilter.SHOW_TEXT);
  var node;
  let list = []
  while ((node = treeWalker.nextNode())) {
    list.push(node)
  }
  // 纯文本节点数组遍历
  list.forEach(function(node) {
    // 纯文本节点切割,替换为span标签
    var replaceArr = node.textContent.split('').map(function(str) {
      var newSpan = document.createElement('span');
      newSpan.textContent = str;
      return newSpan;
    });
    node.replaceWith.apply(node, replaceArr);
  })
}

JS 分割大法,将所有文本内容拆分成单个标签,方案简单粗暴,可能会提高样式布局难度,有潜在风险,故最终未采用该方法,但它较适合对局部个别文案处理、兜底展示或者低端机型处理

2.半角数字转全角

数字为全角时,此时垂直展示的时候,它的展示效果和中文类似,天然“直立向上” ,因而可以将半角数字转成全角数字

数字半角转全角的示例代码如下:

// 数字半转全 0-9 对应 半角对应48-57,全角对应65296-65305
function ToDBC(txtstring) {
    var newNumber = "";
    for(var i = 0; i < txtstring.length; i++) {
        if(txtstring.charCodeAt(i) <= 57 && txtstring.charCodeAt(i) >= 48) {
            newNumber = newNumber + String.fromCharCode(txtstring.charCodeAt(i)+65248);
        } else {
            newNumber = newNumber + txtstring.substring(i, i+1);
        }
    }
    return newNumber;
}

数字半角转全角的方法看似非常完美,但是后续有需要额外考虑哪些不转全角,并且涉及到一些数字计算判断时,还需要把全角转半角(全角数字无法直接参与逻辑运算),展示再转全角,处理起来较为繁琐,故最终没选择此技术方案

数字“直立向上”方案小结

  • CSS的 text-orientation
  • 暴力拆解 DOM
  • 调整数字为全角

关于数字“直立向上”的实现,如果大家有其他好的思考角度或者解决方案,欢迎分享交流~

最终的归纳总结

  • 竖向展示排版通过 writing-mode 可快速实现
  • 对于部分数字需要“直立向上”时,采用 text-orientation:upright 方法
  • 日期类字符(2-4字符)可以通过 text-combine-upright 属性横向合并优化展示

新人写作,内容如有遗留、错漏,欢迎大家指正。也欢迎有同好者一起探讨研究~~~

参考链接