当前位置: 首页 > 科技观察

手机淘宝的柔性设计与实现

时间:2023-03-15 22:49:14 科技观察

手机淘宝从2014年年中开始全面实现柔性设计。什么是灵活的?其实flexible是responsive的低端形态和基础。对于我们来说,最直观的感受就是在超宽屏幕上,网页显示时不会出现两边空白的情况。PC时代人们常说的流体布局,其实就是一种灵活的设计。但是,流体的表达角度是实现,灵活的表达角度是结果。为了与高响应保持一致,我们在这里使用术语灵活。在讨论解决方案之前,您需要了解三个关键概念:PixelPerInch(PPI):现实世界中一英寸的像素数决定了屏幕的显示质量。DevicePixelRatio(DPR):物理像素和逻辑像素的对应关系(px)Resolution:屏幕区域的宽度和高度所占的像素数当我们决定不同屏幕的字体和尺寸单位时,屏幕的这些参数非常重要。场景一——Resolution适配了一个banner图片,当你面对不同的屏幕时,你希望它做什么?在这种场景下,我们主要需要面对分辨率适配的问题。考虑到大多数网页都是垂直滚动的,在不同的屏幕尺寸下,横幅的行为应该始终填充屏幕宽度并始终保持纵横比。最自然的想法是使用百分比宽度,但是如果使用百分比宽度,即width:100%,我们有两种方式来实现固定的宽高比:一种是利用img标签的特性,以及仅在加载图像后设置宽度。这种方式会导致大量重排,而且高度不固定,懒加载等功能难以实现,果断放弃;二是利用before伪元素的margin来扩展高度。这个方法是比较干净的纯css实现。但它没有任何可重用性,需要特定的html结构,所以只好作罢。因此,最合适的解决方案是使用其他相关单位。本来,最合适的单位是vw,意思是视口的宽度。但是,这个单元存在严重的兼容性问题,所以我们不得不放弃。***我们要配合js来做。硬计算也是一种方式,但同样不具备任何可重用性。最后我们选择了rem。我们用js给html设置一个与屏幕宽度成正比的font-size,然后用rem为单位的元素的宽高。这是我们目前的在线解决方案。这几乎是一种Hack用法。已知问题包括:部分安卓机型会丢失rem的小数部分,占用rem单元。不是纯css方案场景2——PPI适配段Text,你希望它在面对不同屏幕时表现如何?显然,我们希望在iPhone3G和iPhone4的Retina屏下看到相同的文字大小,也就是说,我们不希望Retina屏下的文字大小变小。多文本,现在大部分的字体文件都有一些点阵大小,通常是16px和24px,所以我们不希望出现13px和15px这样奇怪的大小。这样的特点决定了场景一中的rem方案并不适合段落文本。因此,段落文字应以px为单位。考虑到Retina,我们使用媒体查询来指定不同的字体。考虑到dpr判断的兼容性,我们改用宽度替换:另一种场景,一些标题文字,希望随着屏幕宽度的增加,我们仍然可以使用rem为单位。35px以上的文字(个人直觉)不需要过多考虑点阵信息,字体的矢量信息也可以很好的渲染。场景三——DPR匹配一个块,设计稿上有一个1像素的边框,你希望它在面对不同的屏幕时表现如何?在这个场景中,需求非常简单。设计者希望这条线在任何屏幕上都是1个物理像素。嗯,这个问题的答案当然不是写1px那么简单。在retina屏幕下,如果你写这样的meta,你永远写不出1px宽度的东西。另外,inlineSVG等元素也会按照逻辑像素进行渲染,整个页面的清晰度会打折扣。所以手机淘宝使用JS动态写入meta标签,代码类似这样:varmetaEl=doc.createElement('meta');varscale=isRetina?0.5:1;metaEl.setAttribute('name','viewport');金属元素。setAttribute('content','initial-scale='+scale+',maximum-scale='+scale+',minimum-scale='+scale+',user-scalable=no');if(docEl.firstElementChild){文档.documentElement.firstElementChild.appendChild(metaEl);}else{varwrap=doc.createElement('div');wrap.appendChild(metaEl);documen.write(wrap.innerHTML);}灵活的解决方案是同时使用rem和px单位+js设置比例和html字体。这些JS的内容可以在我们的开源库ml中找到:https://github.com/amfe/lib.flexible。