「前端」rem 缩放方案 flexible-js 兼容 375px 方案的思路

本文来自尚妆前端团队南洋

发表于尚妆github博客,欢迎订阅。

移动端H5页面rem缩放方案flexible.js兼容375px方案的思路

参考:

移动端高清、多屏适配方案

viewport-and-flexible.js

flexible.js github

一个新的项目复用了一些老页面,老页面是使用375px方案进行移动端适配的,meta[viewport]使用的是<meta name="viewport" content="width=375, user-scalabe=no">,而新页面使用的是flexible.js伸缩方案,动态生成meta[viewport]<meta name="viewport" content="initial-scale=[num], user-scalabe=no">
如何在老页面使用px布局的前提下,新页面使用rem布局,组件也使用rem布局,并且组件可以兼容老页面和新页面是本文的结果。
首先会介绍375px方案和rem方案的实现原理。

375px方案

<meta name="viewport" content="width=375, user-scalabe=no">

375px方案的页面开发过程对新人非常的友好,利用页面的布局视口(layout viewport)为固定值375px,和移动端浏览器窗口的自动缩放功能(视觉视口==布局视口),可以很好的在大部分移动设备上展示375px宽度的内容。

具体的开发前提是设计师给到一份750px宽的设计稿,前端同学根据ps量的像素的50%进行css书写。若一个banner宽度量的为750px,在css中编写为width: 375px。至于为什么是2倍的设计稿,可以参考移动端高清、多屏适配方案这篇文章,可以找到答案。

375px方案相对于把meta[viewport]中的width属性设置成device-width,然后通过媒体查询写几套css规则来说已经是非常方便了。把所有不同屏幕尺寸的手机的布局视口(layout viewport)设置成一个固定的值375px,无需考虑其他屏幕尺寸的情况。

但375px方案的实现原理在某些安卓原生浏览器上有兼容问题,会产生一个重要bug --- 在某些安卓原生浏览器或webview中会出现视觉视口小于布局视口的情况。直观的显示就是页面会出现左右滑动。如下图:

375bug

而在上文也提到了375px方案得以实现就是依靠浏览器的原生能力 --- 迫使视觉视口等于布局视口。我们将这种情况下的document.documentElement.clientWidth(布局视口)window.innerWidth(视觉视口)打印看看。

浏览器的缩放效果没有实现,至于为什么,先看两条关于缩放的总结公式/经验。

一、meta标签内没有设置initial-scale的情况

浏览器计算出的缩放值 = layout viewport width(布局视口) / ideal viewport width(理想视口)

visual viewport width(视觉视口) = 浏览器计算出的缩放值 * ideal viewport width (理想视口)
===》
layout viewport width === visual viewport width // true

经过上述计算会将视觉视口会等于布局视口,布局上的所有内容都会出现在手机屏幕上。出现之前提到的bug的问题出在计算视觉视口上,浏览器会将所有计算出的缩放值都默认等于1,所以不管我们将布局视口设置能375还是其他任意值,视觉视口永远会是1 * ideal viewport width (理想视口)。ps:此款安卓机型的理想视口等于360.

二、meta标签内设置了initial-scale的值的情况

visual viewport width(视觉视口) = initial-scale(meta 标签内设置的初始缩放值) * ideal viewport width(理想视口又称设备独立像素)

layout viewport width = visual viewport width

解释:第二条总结经验正是rem伸缩方案flexiblejs的核心思想,设置了initial-scale后浏览器会计算出视觉视口,继而将布局视口的值自动设置成视觉视口的值。达到在屏幕上完整呈现布局上的内容。

但是在同样的安卓原生浏览器上,不管我们将initial-scale设置成多少,浏览器都默认值为1。所以视觉视口和布局视口永远都等于1 * ideal viewport width这个问题的hack办法在flexible.js里也有所体现。

375px方案就解释到这里,至于为何是375而不是其他的值比如360、320等,可以参考移动端高清、多屏适配方案以及viewport-and-flexible.js, 在后篇文章中也有介绍3种视口的一些概念。

###rem方案

rem方案的目标也是用一套相同的度量标准适配所有屏幕大小的移动设备,在不同屏下进行正确的缩放。假设10rem宽在iphone5上是屏幕宽的一半,那么10rem在iphone6、iphone6plus、三星note等等机型上都显示为屏幕宽的一半。

我们知道rem所对应的px值是基于html标签上的font-size值进行换算的。若

html {
  font-size: 20px;
}

10rem === 200px //true

为了适配缩放所有设备,就要写个脚本动态设置html的fontSize值。同时要对页面的布局视口(layout viewport)和设计稿做一个划分约定,这里就约定这个值为10。(理论上可以任何值)

由以上两幅图可以知道,设计稿的一个区块对应1rem,布局视口的一个区块也对应1rem。而每个机型的布局视口该如何确定,flexible.js利用了上面提到的公式:

visual viewport width(视觉视口) = initial-scale(meta 标签内设置的初始缩放值) * ideal viewport width(理想视口又称设备独立像素)

浏览器自动将 layout viewport width = visual viewport width

之前也提到了initial-scale不为1的情况下部分安卓机型有bug,所以这里可以将initial-scale规定设置成1。

拿iphone6为例:理想视口为375px,经计算布局视口和视觉视口都等于375,html的fontSize等于37.5px。若设计稿量的是10个区块大小,那么在编写css时就写10rem,对应的width等于37。5 * 10 = 375px正好布满整个布局视口。

在flexible.js中对iphone设备的initial-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; // initial-scale

此处将initial-scale根据dpr动态设置是为了解决retina屏下border: 1px问题。而将安卓设备的dpr全部设置成1就是hack了之前提到的initial-scale在部分安卓机子上只能为1的bug。

回到border: 1px问题,有些设计师在750px的设计稿中设计了一条1px的边框线,而这个1px的边框线在各机型上最好的效果实际是占设备物理像素的1px。

拿iphone5和初代iphone为例:若设置initial-scale=1,那么布局视口为320px,但是iphone5的物理像素宽为640px,那就代表了1个css像素包含了4个物理像素(2x2)。而初代iphone的布局视口和物理像素都为320px如图:

在两者手机上显示的效果1px是一模一样的,但是iphone5包含着4倍的物理像素,就取上下高度而言,在iphone5上只用编写border: 0.5px就可以了。

但是部分机型对于0.5是不识别的,会直接赋值0。而我们想要做的就是令border的宽等于1个物理像素。我们可以这样做,根据window.devicePixelRatio属性动态缩放layout viewport,使之与屏幕的物理像素相同。这样我们只用在css里编写border: 1px,对应的就是物理像素的1px,border:1问题完美解决。

两种方案如何兼容

首先要考虑到组件也用rem进行布局,并且组件要在px布局和rem布局中都能兼容。那么就要全局head引入flexible.js的js脚本。

在375px布局方案里meta[viewport]已经设置,那么在flexible脚本中就要进行判断,已经设置viewport的就沿用,不动态创建meta[viewport]。

组件的rem布局要依赖html标签的font-size值,在新页面rem布局中已经实现。而在375px布局中,flexiblejs根据固定layout viewport值-- 375进行计算,那么所有屏幕尺寸下的页面html标签font-size值都为37.5px

还有一个问题,在375px布局中,全局css环境中设置了

html, body {
  font-size: 100%
}

而所有的浏览器实现默认字体大小为16px,所以在老页面中有些字没有设置大小,默认是16px,引入了flexible后html上的font-size为37.5px,body标签上的字体大小就会变成37.5 * 100% = 37.5px,而没有设置字体大小的字体就会变成37.5px,需要在flexible.js中设置针对这种情况。

if (doc.readyState === ‘complete‘) {
        doc.body.style.fontSize = 16 + ‘px‘;
    } else {
        doc.addEventListener(‘DOMContentLoaded‘, function(e) {
            doc.body.style.fontSize = 16 + ‘px‘;
        }, false);
    }

最后的结果就是:

  • 全局引入flexible.js文件。
  • 375px布局的老页面上html标签的font-size固定为37.5px。body上的font-size固定为16px。
  • rem布局的新页面上html标签的font-size随不同机型而不同。
  • 组件编写一律按照rem布局,设计稿为750px,兼容新老页面。

原创文章,转载需谨慎 ~~



本文对你有帮助?欢迎扫码加入前端学习小组微信群:

原文地址:https://www.cnblogs.com/baimeishaoxia/p/11801491.html

时间: 2024-10-11 00:11:20

「前端」rem 缩放方案 flexible-js 兼容 375px 方案的思路的相关文章

vue 的rem 配置和flexible.js的应用

1.环境的配置: C:\Windows\System32\drivers\etc 2.多行注释: 光标放在函数中间,连按两次:"Ctrl+Alt+D",就会出现以下的内容 3.总结使用过程:vue移动端flexible.js结合Muse-ui使用的小坑 1/px to rem 插件(vs code) 使用的时候选中 Alt + Z 2/安装步骤见链接: http://blog.csdn.net/zhanglong_web/article/details/78649717 http://

0082 rem适配方案:less+rem+媒体查询、flexible.js+rem

1.让一些不能等比自适应的元素,达到当设备尺寸发生改变的时候,等比例适配当前设备. 2.使用媒体查询根据不同设备按比例设置html的字体大小,然后页面元素使用rem做尺寸单位,当html字体大小变化,元素尺寸也会发生变化,从而达到等比缩放的适配. 技术方案: 1.less+rem+媒体查询 2.flexible.js+rem 总结: 两种方案现在都存在,方案2 更简单,现阶段无需了解里面的js代码. rem实际开发适配方案1 ①假设设计稿是750px ②假设我们把整个屏幕划分为15等份(划分标准

「标准」的 JS风格

「标准」的 JS风格 2016-10-31 10:09 by 聂微东, 2099 阅读, 21 评论, 收藏, 编辑 首先,这份 JS风格指南已经在我司的前端团队实行半年多了: 其次,在程序员的世界里,从入行到资深都需要面对几个世界级的难题,如: 世界上最好的编辑器是什么? 是用空格还是 TAB?用空格还特么衍生出 2空格 VS 4空格. JS到底要不要写分号? ... 最后,PHP是世界上最好的语言. 一.规范VS自由 对程序员的每个个体来说,有代码规范其实不一定是好事,因为肯定会影响到写码的

前端工程师需要明白的「像素」

场景: 人物:前端实习生「阿树」与 切图工程师「玉凤」 事件:设计师出设计稿,前端实现页面 玉凤:树,设计稿发给你啦,差那么点像素,就叼死你┏(  ̄へ ̄)=? 阿树:~(>_<)~毛问题噶啦~ 阿树:哇靠,为啥你给的设计稿是640px宽 ,iPhone 5不是320px宽吗??? 玉凤:A pixel is not a pixel is not a pixel, you know ? 阿树:(#‵′),I know Google... 为什么会出现以上的情况,难道他们当中一位出错了,摆了这样的

04. 移动web-简洁搞笑的rem适配方案flexble.js

flexble.js 1.手机淘宝团队出品:简洁高效,移动端适配库 2.不需要写媒体查询了,里面js做了处理 3.原理:把当前设备划分为10等分,但是不同设备下,比例还是一致的 4.我们只要确定好当前设备的html文字大小就可以了 比如:当前是750px,只需要把html文字大小设置为75px(750px/10)就可以 5.里面页面元素rem值:页面元素的px值/75 剩余的,让flexible.js来去算 原文地址:https://www.cnblogs.com/foreverLuckySta

Rem自适应js---flexible.min.js

网上看到很多移动端适配的各种方法,由于原来工作中对rem的疏忽,所以决定重新学习rem~ 由于移动端特殊性,本文讲的是如何使用rem实现自适应,或叫rem响应式布局,通过使用一个脚本就可以rem自适应,不用再为各种设备宽度不同而烦恼如何实现自适应的问题. rem是相对于根元素<html>,这样就意味着,我们只需要在根元素确定一个px字号,则可以来算出元素的宽高.1rem=16px(浏览器html的像素,可以设定这个基准值),假如浏览器的html设为64px,则下面的元素则1rem=64px来运

移动端适配--flexible.js

引言: H5适配一直是一个比较普遍的问题,很多文章都会讲,最近开发了一个H5的项目使用了一下淘宝的 flexible.js,写一篇文章自己总结一下. 一.背景介绍: Flexible.js是淘宝公开的一种移动端适配方案,用来解决H5开发中的各个机型适配问题,是一种比较成熟的适配方案. 二.使用方法: 在html头部引入flexible.js,最好放在最头部,重构时使用rem替代px像素即可,flexible会做好所有适配.换算关系为1rem对应1/10设计尺寸,如ipone6设计尺寸为750px

技术人员应对「考核」的一些思考

来这个公司实习已经半年多了,在年前经历了一次年终考核,最终对我的工作的评级是 C(及格-符合当前职位的工作),让我不禁思考自己在项目中的一些工作的问题,为什么我是C?是我做的不够好吗?或者说在哪里做的不够好? 从考核流程来看,基本上是 CTO 与 Team Leader 对团队成员的「年终总结与次年工作计划」进行Rank,个人狭义的认为「考核」的主要支持材料就是这个总结了. 他山之石 其他公司是怎么考核的呢?说实话我也不太清楚,刚入行,只能通过搜索了解,在网上了解到有以下几种:发精品博客.发论文

flexible.js框架改写

前一阶段拜读了阿里团队的flexible.js,但是flexible的封装感觉还是不完美,因为flexible还是要依赖less/sass之类的编译执行,所以就存了一些问题,我把这些问题进行整理. 优点: 1.代码量明显减少 2.开发效率变高,css管理式开发,css逻辑清晰 3.less+flexible.js能否适配各种手机型号,实现各个尺寸屏幕的兼容 4.less学习成本低(几乎为零) 缺点: 1.less编译成css执行,团队开发git版本控制器的坑,这个不多说了 2.因为是less编译