Skip to content

rem自适应方案 #3

@longyiyiyu

Description

@longyiyiyu
Contributor

H5自适应改造方案——rem方案

原理

之前我们H5页面使用的方案是设置viewport meta头,让浏览器帮我们把页面缩放,使得页面看起来好像是自适应。实际上这不是自适应,只是在中小屏设备上,看起来差距不大,问题不明显而已。

现在大屏高清设备流行,自适应的问题也越来越明显了。在大屏设备上,课程封面小,title被拉长,文字小,按钮扁等问题越来越突出,已经达到不能忍受的程度,因此需要一套自适应的方案。

页面缩放

在viewport meta头里,取消让浏览器自动缩放页面,页面的自适应由页面自身管理。
因为有dpr的问题,为了统一管理,让浏览器帮我们根据dpr缩小页面,比如dpr=2,就缩小0.5让页面统一处在dpr=1的环境中。

rem

rem是一个半相对单位,它相对的是html(或body)元素的font-size值,例如有html { font-size: 10px; },则1rem = 10px。

当html元素的font-size是根据设备宽度自适应时,使用rem的页面也就会有自适应的特性。

文字

根据以下两个原因,对于文字使用px:

  • 在大屏设备希望看到更多的文字
  • 中文点阵最好是在12px,14px,16px这种尺寸,使用rem就会无法避免使用13px,15px尺寸,这样文字会显示的很奇怪

没有浏览器帮助我们缩放页面,在高清设备里面需要我们手动对文字进行缩放,为了方便这个而不需要写media query,页面在计算html的font-size值的同时,会设置一个data-dpr的属性。这时文字的media query就可以这样写:

p { font-size: 12px; }  /* dpr = 1 */
[data-dpr="2"] p { font-size: 24px; }   /* dpr = 2 */
[data-dpr="3"] p { font-size: 36px; }   /* dpr = 3 */

规范

  1. 在head头引入初始化js脚本,可以使用两种代码:

    • 淘宝移动端自适应方案开源代码,注:这里的因子是10,即font-size = W/10
    • 腾讯课堂公众号最新代码里面(路径:src/inline/rem.html),里面的代码是淘宝现网代码copy下来的,与开源代码对比过,大致一样。注:这里的因子是16,即font-size = W/16
  2. 开发时,假如视觉稿宽度是640,则最好使用第二种方案,选择16作为因子,则比例为640/16=40。那么,页面所有的rem数值的换算公式为:在视觉稿中的px数值/40。

    以后会开发一个fis插件,在开发时只需填入视觉稿中的px数值,由fis插件帮助我们自动换算,在插件开发出来之前,先人工计算吧。

  3. 文字使用px单位,同时需要写media query,借助html元素上面的data-dpr属性,详见原理部分。

Activity

miniflycn

miniflycn commented on Apr 27, 2015

@miniflycn
Member

good job,解决了我周四的问题

longyiyiyu

longyiyiyu commented on May 5, 2015

@longyiyiyu
ContributorAuthor

实践所得——重构公众号首页

  1. 在重构前,针对设计稿评估是否真的需要用到rem方案,如果存在以下两点都需要考虑使用rem方案
    • 稀疏布局
      由前面的【原理】可知,非自适应的页面通过浏览器的缩放在不同手机之间的显示差不多,关键只在于这些差异能不能容忍,如果可以容忍,那么完全可以不用自适应方案。
      稀疏布局不像列表结构,页面元素不多。其中某些元素需要宽度自适应(否则太窄),这时高度也必须跟着自适应(否则太扁),那么里面的字体也必须跟着自适应(否则太空旷,除非多几行)
    • font-size < 12px
      font-size小于12px的字体在3倍屏下面会显得很小
  2. 一般来说,640的稿子量出来的字体是data-dpr="2"的,750(ip6)也是data-dpr="2"的,data-dpr="1"和data-dpr="3"的按倍数计算,同时可以做一下微调。
    一个640px宽的屏幕,它可能是6401,也可能是3202,不管是哪一种,页面的布局(使用rem单位)长得都是一样的,那字体要怎么度量?这个问题放在以前就是一个@Medie的事情,但是现在不想这样做,希望通过[data-dpr="xx"]来实现,只有2个临界点,那么问题是,你怎么知道640的页面是1dpr还是2dpr?这个只能通过普遍机型的经验来确定,一般640,750都是2dpr的,因此对于640的稿子量出来的字体大小是属于data-dpr="2"的。
    如果我们的页面需要适应pad,那么有两个方案,一个是定宽;另一个就是在html元素上面再加上一个data-device了,因为640*1会在pad中出现。
  3. 图片需要3倍高清,需要视觉稿提供,多倍图(包括课程封面)注意
    • css实现时,可以和font-size的处理一样,通过[data-dpr="xx"]来设置不同的图片
    • js实现也可以通过html的data-dpr属性值来设置。
    • 首屏图片最好用css,使用background,如果需要img,则只能内嵌js代码
    • 非首屏图片的话img和background都可以用,在lazyload里面实现
  4. 小数点问题
    • 导致 |width - background-size| = 1,因此会出现截边问题,因此需要设置background-size: cover。因为只相差1px,对background-position影响不大,因此依然使用rem
    • 用css拼出来的图标也会出问题。图标问题有3个方案:
      • 图片:需要多倍图,在一些性能要求高的页面需要在不同屏使用不同清晰度的图片,多倍图维护起来是很麻烦的。
      • svg:android 2.3不支持,什么时候可以抛弃android 2.3,就可以使用svg了。
      • icofont:只支持灰度图,较简单,需要svg制作,比较麻烦。
        相比较而已,还是支持icofont方案,原因如下:
        • 大小,颜色,底色可控
        • 支持内嵌与外链两种方式,而且在移动端,可以避免pc端的许多问题
  5. 使用icofont有以下建议:
    • 把字符资源当成一般的图片资源即可
    • 需要共享使用外链,不需要使用内嵌
    • 外链时,字符文件用gzip压缩
    • 只需要trueType(.ttf)格式
    • 一个字符资源不要包含太多图标,测试时,3个5k,10个7k
  6. js计算css的时候,需要完全动态计算,结果不一定需要使用rem单位,如果需要使用rem单位,则记住换算公式:1rem = W/16px
  7. 不需要使用rem的属性(为以后的自动计算工具做准备)
    • font-size
    • border系,除了border-radius
  8. 自动计算工具设计
    • 配置:
      • 设计稿宽度,默认640
      • rem换算因子,默认16
      • dpr,默认2
      • 不自动转换为rem的属性正则,默认[/^font-size$/, /^border/]
      • 自动转换为rem的属性正则,默认[/^border-radius$/]
    • 逻辑
      • background-size自动设置为background-size: cover;
      • 所有的px单位都转换为相应的rem,除了配置项
      • 所有包含font-size的规则,补齐另外2种屏的值
    • 规范
//规范在实现时可改
.test {
    font-size: 12px#r;  /* 转换为rem */
    margin: 5px#nr;     /* 不转换为rem */
}

.test-a {
    font-size: 12px#22|34;
}
//自动生成以下代码,假设配置dpr: 1
.test-a { font-size: 12px; }
[data-dpr="2"] .test-a { font-size: 22px; }
[data-dpr="3"] .test-a { font-size: 34px; }
litten

litten commented on May 5, 2015

@litten

good!很好的分享实践

ousiri

ousiri commented on Jun 9, 2015

@ousiri
Contributor

为什么font-size和border不需要设置rem?

herbertliu

herbertliu commented on Jun 16, 2015

@herbertliu
Member

@ousiri 这里主要是考虑后续我们希望能够直接通过工具生成rem或者font-size。

xrds

xrds commented on Jul 8, 2015

@xrds

为什么咋 安卓上 布局会变大阿 怎么解决阿

herbertliu

herbertliu commented on Jul 10, 2015

@herbertliu
Member

@xrds 具体指哪里?详细描述下场景,展示和屏幕尺寸有关。

xrds

xrds commented on Jul 14, 2015

@xrds

@herbertliu dpr的问题 第一次用不太了解。。。 谢谢

herbertliu

herbertliu commented on Jul 20, 2015

@herbertliu
Member

@xrds dpr本身是表示显示像素和物理像素的比。一般我们用的是2倍像素,这里借助data-dpr设置,来手动管理手机分辨率(再去掉了meta viewport二倍像素设置后)。根据这个data-dpr的设置,可以在css中设置对应的想要设置的值,如:
image

xrds

xrds commented on Jul 20, 2015

@xrds

@herbertliu 谢谢,河伯详细讲解 我现在已经有了大概的了解了。。。

luckymore

luckymore commented on Sep 10, 2015

@luckymore

好腻害,,,这能写个插件刁刁哒

qc-zhan

qc-zhan commented on Sep 10, 2015

@qc-zhan

background-position用rem定位雪碧图的话会出现偏差,请问你们是怎么处理了,是用px加dpr?

herbertliu

herbertliu commented on Sep 11, 2015

@herbertliu
Member

@luckymore 插件我们看看尽快能否输出

luckymore

luckymore commented on Sep 11, 2015

@luckymore

@herbertliu 划擦O(∩_∩)O,,,河伯大爱无疆,期待

12 remaining items

luckymore

luckymore commented on Oct 26, 2015

@luckymore

@herbertliu

河伯,我没表达清楚。。。
html的**[font-size]**是js根据手机的大小决定的,比如说iPhone6 375 × 627,js计算出来的值是这样的:

<html lang="en" data-dpr="2" style="font-size: 75px;">

现在我不理解的是,我从拿到一个1080 × 1920设计稿开始,为它选择一个font-size基 ‘ s’ 来计算:
设计稿里有个300 × 100 的按钮,则:

.btn {
  width: (300/s)rem;
  heigth: (100/s)rem;
}

这其中的**’s‘**值是怎么确定的。。。有点白痴的问题呢😄

herbertliu

herbertliu commented on Oct 26, 2015

@herbertliu
Member

@luckymore 你说的是用那个js设置吧。首先根据iPhone6 375 × 627,
image
dpr为2,然后页面实际像素宽度
image
这里采用的dpr倍数是:10,所以宽度为计算出来的宽度是75px

那么,实际开发中。从上面的分析可以看到,倍数是10,,针对1080 × 1920。1080->750(iphone6为例)->10rem;所以这里1rem=108px(这里指的是视觉稿1rem对应的108px)。因此针对,300 × 100的按钮。对应的rem为300/108=2.78rem。

另外,我们采用的是倍数是16,即:1rem=46.875px(iphone6为例),视觉稿中:1rem=67.5px。

luckymore

luckymore commented on Oct 27, 2015

@luckymore

@herbertliu

谢谢啦

小弟比较愚钝,,还请河伯不要烦我。。

ronyland

ronyland commented on Nov 6, 2015

@ronyland

说得很好

majiang666

majiang666 commented on Mar 18, 2016

@majiang666

已经解决,应用这个js头部的它是需要去掉的,js会自动添加
<meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">

demo:http://www.love85g.com/code/

p { font-size: 12px; } /* dpr = 1 */

下边两句为什么在我测试页面不起作用,求解
[data-dpr="2"] p { font-size: 24px; } /* dpr = 2 /
[data-dpr="3"] p { font-size: 36px; } /
dpr = 3 */

herbertliu

herbertliu commented on Mar 23, 2016

@herbertliu
Member

@majiang666 效果是什么样子?有测试路径吗?

majiang666

majiang666 commented on Mar 30, 2016

@majiang666
git-lt

git-lt commented on May 7, 2016

@git-lt

开发时,假如视觉稿宽度是640,则最好使用第二种方案,选择16作为因子,则比例为640/16=40。那么,页面所有的rem数值的换算公式为:在视觉稿中的px数值/40

这里为什么要使用16做为因子? 如果是640下设计稿,根字体计算出来为100,这样不是更好计算rem的大小吗?

herbertliu

herbertliu commented on May 9, 2016

@herbertliu
Member

@git-lt 其实这里的用多少没关系的,而且计算这个可以通过插件来直接支持,开发仍然只需关注px,查看fis-parser-rem

suming1016

suming1016 commented on May 19, 2016

@suming1016

html 后面那个font-size可以动态取值的;
图片自适应怎么办?根据dpr设计不同的图吗,有没有什么好方法()

suming1016

suming1016 commented on May 19, 2016

@suming1016

@herbertliu 链接打不开404

herbertliu

herbertliu commented on May 20, 2016

@herbertliu
Member
SKing7

SKing7 commented on Jan 5, 2018

@SKing7

没看到border怎么适配啊

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @SKing7@litten@miniflycn@herbertliu@longyiyiyu

        Issue actions

          rem自适应方案 · Issue #3 · imweb/mobile