手淘布局

使用Flexible实现手淘H5页面的终端适配rem自适应布局-移动端自适应必备

或者直接加载阿里CDN的文件:

另外强烈建议对JS做内联处理,在所有资源加载之前执行这个JS。执行这个JS后,会在元素上增加一个data-dpr属性,以及一个font-size样式。JS会根据不同的设备添加不同的data-dpr值,比如说2或者3,同时会给html加上对应的font-size的值,比如说75px。

如此一来,页面中的元素,都可以通过rem单位来设置。他们会根据html元素的font-size值做相应的计算,从而实现屏幕的适配效果。

除此之外,在引入lib-flexible需要执行的JS之前,可以手动设置meta来控制dpr值,如:

其中initial-dpr会把dpr强制设置为给定的值。如果手动设置了dpr之后,不管设备是多少的dpr,都会强制认为其dpr是你设置的值。在此不建议手动强制设置dpr,因为在Flexible中,只对iOS设备进行dpr的判断,对于Android系列,始终认为其dpr为1。

if (!dpr && !scale) {

var isAndroid = win.navigator.appVersion.match(/android/gi);

var isIPhone = win.navigator.appVersion.match(/iphone/gi);

var devicePixelRatio = win.devicePixelRatio;

if (isIPhone) {

// iOS下,对于2和3的屏,用2倍的方案,其余的用1倍方案

if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {

dpr = 3;

} else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){

dpr = 2;

} else {

dpr = 1;

}

} else {

// 其他设备下,仍旧使用1倍的方案

dpr = 1;

}

scale = 1 / dpr;

}

flexible的实质

flexible实际上就是能过JS来动态改写meta标签,代码类似这样:

var metaEl = doc.createElement('meta');

var scale = isRetina ? 0.5:1;

metaEl.setAttribute('name', 'viewport');

metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');

if (docEl.firstElementChild) {

document.documentElement.firstElementChild.appendChild(metaEl);

} else {

var wrap = doc.createElement('div');

wrap.appendChild(metaEl);

documen.write(wrap.innerHTML);

}

事实上他做了这几样事情:

动态改写标签

给元素添加data-dpr属性,并且动态改写data-dpr的值

给元素添加font-size属性,并且动态改写font-size的值

案例实战

了解Flexible相关的知识之后,咱们回到文章开头。我们的目标是制作一个适配各终端的H5页面。别的不多说,动手才能丰衣足食。

创建HTML模板

再来一波


正如前面所介绍的一样,首先加载了Flexible所需的配置:

这个时候可以根据设计的图需求,在HTML文档的中添加对应的HTML结构,比如:

  • {poductName}

    双11价

    ¥{price}

    ({preferential})

    {activityType}

    {activeName}

    这仅是一个示例文档,大家可以根据自己风格写模板。

    为了能更好的测试页面,给其配置一点假数据:

    //define data

    var pageData = {

    sections:[{

    "brannerImag":"http://xxx.cdn.com/B1PNLZKXXXXXaTXXXXXXXXXXXX-750-481.jpg",

    items:[{

    "itemLink": "##",

    "imgSrc": "https://placeimg.com/350/350/people/grayscale",

    "poductName":"Carter's1年式灰色长袖连体衣包脚爬服全棉鲸鱼男婴儿童装115G093",

    "price": "299.06",

    "preferential": "满400减100",

    "activityType": "1小时内热卖5885件",

    "shopLink":"##",

    "activeName": "马上抢!"

    }

    ....

    }]

    }]

    }

    接下来的工作就是美化工作了。在写具体样式之前,有几个点需要先了解一下。

    把视觉稿中的px转换成rem

    读到这里,大家应该都知道,我们接下来要做的事情,就是如何把视觉稿中的px转换成rem。在此花点时间解释一下。

    首先,目前日常工作当中,视觉设计师给到前端开发人员手中的视觉稿尺寸一般是基于640px、750px以及1125px宽度为准。甚至为什么?大家应该懂的(考虑Retina屏)。

    正如文章开头显示的示例设计稿,他就是一张以750px为基础设计的。那么问题来了,我们如何将设计稿中的各元素的px转换成rem。

    我厂的视觉设计师想得还是很周到的,会帮你把相关的信息在视觉稿上标注出来。

    目前Flexible会将视觉稿分成100份(主要为了以后能更好的兼容vh和vw),而每一份被称为一个单位a。同时1rem单位被认定为10a。针对我们这份视觉稿可以计算出:

    1a  = 7.5px

    1rem = 75px

    那么我们这个示例的稿子就分成了10a,也就是整个宽度为10rem,对应的font-size为75px:

    手淘布局_第1张图片

    这样一来,对于视觉稿上的元素尺寸换算,只需要原始的px值除以rem基准值即可。例如此例视觉稿中的图片,其尺寸是176px * 176px,转换成为2.346667rem * 2.346667rem。

    如何快速计算

    在实际生产当中,如果每一次计算px转换rem,或许会觉得非常麻烦,或许直接影响大家平时的开发效率。为了能让大家更快进行转换,我们团队内的同学各施所长,为px转换rem写了各式各样的小工具。

    CSSREM

    CSSREM是一个CSS的px值转rem值的Sublime Text3自动完成插件。这个插件是由@正霖编写。先来看看插件的效果:

    手淘布局_第2张图片

    有关于CSSREM如何安装、配置教程可以点击这里查阅。

    CSS处理器

    除了使用编辑器的插件之外,还可以使用CSS的处理器来帮助大家处理。比如说Sass、LESS以及PostCSS这样的处理器。我们简单来看两个示例。

    Sass

    使用Sass的同学,可以使用Sass的函数、混合宏这些功能来实现:

    @function px2em($px, $base-font-size: 16px) {

    @if (unitless($px)) {

    @warn "Assuming #{$px} to be in pixels, attempting to convert it into pixels for you";

    @return px2em($px + 0px); // That may fail.

    } @else if (unit($px) == em) {

    @return $px;

    }

    @return ($px / $base-font-size) * 1em;

    }

    除了使用Sass函数外,还可以使用Sass的混合宏:

    @mixin px2rem($property,$px-values,$baseline-px:16px,$support-for-ie:false){

    //Conver the baseline into rems

    $baseline-rem: $baseline-px / 1rem * 1;

    //Print the first line in pixel values

    @if $support-for-ie {

    #{$property}: $px-values;

    }

    //if there is only one (numeric) value, return the property/value line for it.

    @if type-of($px-values) == "number"{

    #{$property}: $px-values / $baseline-rem;

    }

    @else {

    //Create an empty list that we can dump values into

    $rem-values:();

    @each $value in $px-values{

    // If the value is zero or not a number, return it

    @if $value == 0 or type-of($value) != "number"{

    $rem-values: append($rem-values, $value / $baseline-rem);

    }

    }

    // Return the property and its list of converted values

    #{$property}: $rem-values;

    }

    }

    有关于更多的介绍,可以点击这里进行了解。

    PostCSS(px2rem)

    除了Sass这样的CSS处理器这外,我们团队的@颂奇同学还开发了一款npm的工具px2rem。安装好px2rem之后,可以在项目中直接使用。也可以使用PostCSS。使用PostCSS插件postcss-px2rem:

    var gulp = require('gulp');

    var postcss = require('gulp-postcss');

    var px2rem = require('postcss-px2rem');

    gulp.task('default', function() {

    var processors = [px2rem({remUnit: 75})];

    return gulp.src('./src/*.css')

    .pipe(postcss(processors))

    .pipe(gulp.dest('./dest'));

    });

    除了在Gulp中配置外,还可以使用其他的配置方式,详细的介绍可以点击这里进行了解。

    配置完成之后,在实际使用时,你只要像下面这样使用:

    .selector {

    width: 150px;

    height: 64px; /*px*/

    font-size: 28px; /*px*/

    border: 1px solid #ddd; /*no*/

    }

    px2rem处理之后将会变成:

    .selector {

    width: 2rem;

    border: 1px solid #ddd;

    }

    [data-dpr="1"] .selector {

    height: 32px;

    font-size: 14px;

    }

    [data-dpr="2"] .selector {

    height: 64px;

    font-size: 28px;

    }

    [data-dpr="3"] .selector {

    height: 96px;

    font-size: 42px;

    }

    在整个开发中有了这些工具之后,完全不用担心px值转rem值影响开发效率。

    文本字号不建议使用rem

    前面大家都见证了如何使用rem来完成H5适配。那么文本又将如何处理适配。是不是也通过rem来做自动适配。

    显然,我们在iPhone3G和iPhone4的Retina屏下面,希望看到的文本字号是相同的。也就是说,我们不希望文本在Retina屏幕下变小,另外,我们希望在大屏手机上看到更多文本,以及,现在绝大多数的字体文件都自带一些点阵尺寸,通常是16px和24px,所以我们不希望出现13px和15px这样的奇葩尺寸。

    如此一来,就决定了在制作H5的页面中,rem并不适合用到段落文本上。所以在Flexible整个适配方案中,考虑文本还是使用px作为单位。只不过使用[data-dpr]属性来区分不同dpr下的文本字号大小。

    div {

    width: 1rem;

    height: 0.4rem;

    font-size: 12px; // 默认写上dpr为1的fontSize

    }

    [data-dpr="2"] div {

    font-size: 24px;

    }

    [data-dpr="3"] div {

    font-size: 36px;

    }

    为了能更好的利于开发,在实际开发中,我们可以定制一个font-dpr()这样的Sass混合宏:

    @mixin font-dpr($font-size){

    font-size: $font-size;

    [data-dpr="2"] & {

    font-size: $font-size * 2;

    }

    [data-dpr="3"] & {

    font-size: $font-size * 3;

    }

    }

    有了这样的混合宏之后,在开发中可以直接这样使用:

    @include font-dpr(16px);

    当然这只是针对于描述性的文本,比如说段落文本。但有的时候文本的字号也需要分场景的,比如在项目中有一个slogan,业务方希望这个slogan能根据不同的终端适配。针对这样的场景,完全可以使用rem给slogan做计量单位。

    CSS

    本来想把这个页面的用到的CSS(或SCSS)贴出来,但考虑篇幅过长,而且这么简单的页面,我想大家也能轻而易举搞定。所以就省略了。权当是给大家留的一个作业吧,感兴趣的可以试试Flexible能否帮你快速完成H5页面终端适配。

    效果

    最后来看看真机上显示的效果吧。我截了两种设备下的效果:

    iPhone4

    手淘布局_第3张图片

    iPhone6+

  • 你可能感兴趣的:(手淘布局)