Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

移动端自适应 #9

Open
Alan110 opened this issue Nov 9, 2017 · 0 comments
Open

移动端自适应 #9

Alan110 opened this issue Nov 9, 2017 · 0 comments

Comments

@Alan110
Copy link
Owner

Alan110 commented Nov 9, 2017


title: 移动端响应式解决方案
date: 2017-03-13 19:13:21
tags:

移动端尺寸不一,所以需要一套自适应的方案。
需要考虑我们的场景,有些时候,我们只需要宽度按设备尺寸伸缩,纵向上可以是固定的值
有时候,我们需要横向,纵向上都能按设备尺寸伸缩,例如铺满屏幕的应用。

设备适配问题,主要场景其实也就2个

  1. 长文档流的
    按尺寸等比缩放就可以了,可以用rem动态计算font-size
  2. fullpage,全屏的应用
    要么百分比,但是可能会有拉伸
    要么切图配合,内容尽可能在中间,再加上背景图片去做适配

为什么移动端会有尺寸适配的问题

概念

物理像素(Device Pixels)

真实物理设备上的像素点, 单位是px,但也是相对的,因为我的点可能比你的点小

逻辑像素(设备独立像素)

逻辑像素是一个相对的抽象概念,并不是实际的具体长度。比如css像素,它只是一个单位,具体渲染出来有多大得看设备。

dpr (Device pixel ratio)

  • 表示每个逻辑像素(css)有几个物理像素
  • dpr = 物理像素 / css像素
  • window.devicePixelRatio 可以直接获取

dpi/ppi (Dots Per Inch / Pixel Per Inch)

  • 像素密度,每英寸的像素点个数。
  • Math.sqrt(750750 + 13341334) / 4.7 = 326ppi // 屏幕对角线的像素尺寸 / 物理尺寸(inch)

viewport

  • 视口,桌面上视口宽度等于浏览器宽度,也等于css像素,但在手机上有所不同 。
  • 它也是一个虚拟的概念,因为手机的分辨率高,在没有缩放的情况下,手机上的视口要比屏幕宽度大得多,但它实际尺寸就是屏幕那么大,所以就只好缩小网页,将其容纳于视口之中。
  • , 所以有了这个经典的meta标签,设置视口width=device-width 。
  • 这也是为什么手机上能双指缩放

为什么要做自适应

正是因为移动端的分辨率高,物理尺寸小
当设置 width=device-width 时,会将物理像素viewpoint强行浓缩到手机的物理尺寸之中。此时就会有一个dpr的值 = 物理像素/物理尺寸 , 即一个css像素是2个物理像素渲染的。

这样理论上看起来不会有什么问题了,但是图片会显得很模糊,原因是图片是按像素点渲染的,而实际的像素点要多一倍,或者2培,所以模糊

解决方案就是用 x2, x3 的图片,写的时候写1倍数值

另外就是1px问题,css写了1px,而实际看起来是2px或者3px,看起来线条会很粗,原因就是按dpr浓缩的问题。

所以需要单独对1px问题做适配

0.5 px
scale
背景图片
渐变

虽然做了这些适配,但是在小屏幕上,或者大屏幕看起来就不协调了,50px在不同尺寸下不一定合理

  • 可以通过媒体查询,按情况判断

  • 通过rem等比缩放页面

页面所有尺寸单位都基于html标签上的字体,结合媒体查询就能实现等比缩放,不过过渡不平滑

动态设置rem

根据设置宽度,动态设置rem,可以实现平滑过渡

满屏模式

满屏模式的应用,不能等比缩放,因为不同设置尺寸不同,缩放后的页面不一定能适配1屏幕。

不能用高度百分比,因为设备高度不同

具体方案比较

媒体查询

这个不用说了,就一个if , else 的问题

百分比

百分比布局只能用在横向上,比如宽度, 并且它是参照父元素的宽度。
高度百分比,需要html,body 等一层一层的往下写高度,才能有参照,参照的是父元素的高度

  • 需要层层继承父元素的宽,高
  • 但是在高度上使用百分比,在不同机型上会有拉伸效果。比如图片,因为图片的伸缩比例和设备的比例是不同的。
  • 其中有个坑就是margin,padding,它的百分比是参照的父元素的宽度。 所以用百分比布局,如果要在纵向上自适应,就相当麻烦了。

但这个特性可以用来解决已知图片比例的自适应问题。
因为padding是按父元素的宽度来计算百分比的,在我们知道图片比例的情况下,可以通过padding来根据宽度自适应计算出高度。

.wrap{
    height : 0;
    padding-top : 75%;
}

.img{
    position : absolute;
    top : 0;
    left : 0;
    width : 100%;
    height : 100%;
}

百分比绝对定位

不需要层层继承父元素的宽,高,只需要参照最外层的定位元素就可以了。
缺点就是所有元素都脱离了的文档,采用平面定位的方式来布局。

动态计算rem

既然要伸缩,就需要一个统一的参照标准,这是最好的。

在rem是参照html元素的字体大小, 可以做到所有元素有统一的参照。

不过rem的布局,在缩小时不一定能完全按比例缩小。

rem 默认是1rem=16px

rem的换算

手机上的分辨率高,一个css像素点往往是几个物理像素点组成, 所以ue给的psd量的尺寸需要经过换算,

iPhone6 375设备宽度 750设计稿宽度 正好是2倍
6s 414设备宽度 1125设计稿宽度 3倍

下面是一个用js动态计算html的rem的例子

(function setResponseRem(basePx, width) {
    var doc = document,
        win = window,
        docEl = doc.documentElement,
        resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
        timer = null,

        recalc = function () {
            clearTimeout(timer);
            timer = setTimeout(function () {
                var viewportWidth = docEl.getBoundingClientRect().width || docEl.clientWidth;
                if (!viewportWidth) return;
                docEl.style.fontSize = basePx * (viewportWidth / width) + 'px';
            }, 10);
        };

    recalc();

    win.addEventListener(resizeEvt, recalc, false);
})(100,750);

rem自适应,css=实际图的px / 100
basePx : 100 ,换算基准, 1rem等于多少px,这个值可以随意定,因为后续px换算rem时会除以这个值,设为100只是为了方便计算
width : 750 代表设计稿宽度
viewportWidth : 代表设备宽度,css像素
viewportWidth / width : 缩放比例, 其实就 1/dpr
fontSize : 实际的html上的字体大小

我们的换算基准是固定的,缩放的任务交给了rem

动态计算meta标签

<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"/>
从前面的viewport的知识,我们知道,viewpoint是可以进行缩放的,一般情况下,我只是把viewpoint设置成了设备的css宽度,并且没有缩放。通过rem动态计算来实现缩放。其实也可以用它来实现响应式缩放。
通过js计算出当前设备的dpr
scale = 1 / dpr
动态设置meta标签的scale缩放程度。

rem我们也用,只不过它只是作为一个写法标准,缩放的任务是交给了meta 标签的scale属性。

lib-flexable

这是淘宝沉淀的自适应方案,就是采用动态计算meta标签的scale和rem,来做的。
有个关键点是,需要结合设计稿,css写尺寸就是设计稿量出来的尺寸,然后根据dpr,动态设置viewport的scale标签,来进行缩放,此方案可以解决1px问题。

rem 和viewpoint,scale 是2个维度的东西, viewport , scale 是为了解决width=device-width 造成的1px问题。

rem只是一个辅助缩放参考单位

原理 :

  1. 默认也是使用viewpoint缩放 + rem 实现, 字体是另外一套缩放方案,根据dpr倍数缩放
  2. 只兼容了ios, 安卓的dpr都是1,看起来没什么问题。

注意:

  1. 如果是瀑布流式的页面,使用此方案没有什么问题,字体可以按dpr倍数缩放,小大机型上看到的文字更多。如果是绝对定位的页面,那就不能使用dpr方案缩放文字,只能用rem,原因是dpr倍数缩放会保证文字的大小在所有机型上一致,但是文字和绝对定位的top,rem 将不能匹配。如果是大段文字,拆分成几个绝对定位元素拼接,那么位置对齐就会有问题。

  2. 如果是瀑布流式页面,使用此方案没问题,如果是全屏覆盖的翻页场景,此方案图片缩放会有问题,高度上的缩放可能会超出1屏幕, 流式页面可以滚动,所以没问题。

flexbox

弹性布局对移动端比较友好,功能比inline-block强大,在横向上的布局,建议用flexbox
移动端兼容,建议使用autoprefix

  .f-box{
    display: flex;
    flex-wrap: nowrap;
  }

  .f-box-cld{
    flex : 1;
    width: 40%;
  }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant