说明:以下内容来自CSDN,如有侵权,请立刻联系博主(我),我将删除该内容。

原文链接  https://blog.csdn.net/u013778905/article/details/77938784

先上体验地址:http://jiguang.qq.com/jiguang_app/kapian/html/card-query.html?from=singlemessage

扫描二维码:

问题

翻到文章底部(反思1024),查看最新解决方案。

rem布局在加载的时候会出现元素一开始很小,闪烁一下恢复正常大小,这是怎么回事呢?为此,我们来探讨一下!

rem的布局具体不介绍了吧,你应该已经掌握或者会用了。

这里我的设计稿是750px的,以下是我用来动态设置html根元素font-size的代码,这里我设置了最大值100px哈!

!(function(doc, win) {
var docEl = doc.documentElement,
resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
recalc = function() {
var clientWidth = docEl.clientWidth;
if (!clientWidth) return;
if (clientWidth < 750) {
docEl.style.fontSize = 100 * (clientWidth / 750) + 'px';
} else {
docEl.style.fontSize = '100px';
}
};
if (!doc.addEventListener) return;
win.addEventListener(resizeEvt, recalc, false);
doc.addEventListener('DOMContentLoaded', recalc, false);
})(document, window);

我新建了一个common.js文件,把该js代码放里面,然后在</body>前引入

<script src="js/common.js"></script>
  • 1

写好页面后发布看下,我们会看到html元素先很小,闪烁一下又正常了,虽然不影响功能,但是这给用户的体验是不行的啊,太明显了!

正常应该是:

实际情况是:

解决

模拟弱网环境,通过查看代码发现,DOM在渲染出来的时候,html根元素font-size的大小,js还没有设置进去。如下图

设想一:既然js看上去是执行的晚了,那我们就把js放在head中怎么样? 
测试发现结果还是一样!

设想二:是不是通过外链引入js会耗费加载时间,我们直接把这段js放在</body>前怎么样? 
测试发现结果还是一样!

设想三:是不是js代码放head中会快点? 
测试发现结果还是一样!

算了,不设想了,这里我们就需要清楚,css/js对DOM树渲染的影响了。

  • CSS(外链或内联)会阻塞整个DOM的渲染(Rendering),然而DOM解析(Parsing)会正常进行
  • 很多浏览器中,CSS会延迟脚本执行和DOMContentLoaded事件
  • JS(外链或内联)会阻塞后续DOM的解析(Parsing),后续DOM的渲染(Rendering)也将被阻塞
  • JS前的DOM可以正常解析(Parsing)和渲染(Rendering)

说明: 
无论是外链CSS还是内联CSS都会阻塞DOM渲染(Rendering),然而DOM解析(Parsing)会正常进行。 这意味着在CSS下载并解析结束之前,它后面的HTML都不会显示。 这也是为什么我们把样式放在HTML内容之前,以防止被呈现内容发生样式跳动。 当然代价就是显示延迟,所以性能攸关的站点都会内联所有CSS。

很多浏览器中CSS还会延迟脚本执行和DOMContentLoaded事件触发(该事件就是jQuery的dom ready)。

不论是内联还是外链JavaScript都会阻塞后续DOM解析(Parsing),当然后续DOM的渲染(Rendering)也被阻塞了。 之所以DOM解析(Parsing)需要暂停, 是因为脚本中可能会包含类似document.write的语句,即脚本有可能改变当前DOM树。

值得注意的是JavaScript只会阻塞后续的DOM而非整个DOM,这意味着前面的DOM可以被正确地解析以及渲染。 这也是为什么我们把脚本放在页面底部:脚本仍在下载时页面已经可以正常地显示了。

下图可以表明资源加载时会先加载css再加载js。

结论: 
从html入手无法解决问题,那我们就从css入手吧! 
上面说了,既然我们的css都会选择优先加载,防止跳动,那我们是不是可以一开始就让网页是正常显示的呢,也就是说,我们来设置html的font-size属性,这里我们通过媒体查询,把相对应的设备区间的根元素font-size列举出来,因为我们是750px的设计稿,而且我们的开发方式是1rem=100px(如果你了解rem的话你应该理解),也就是说,在iPhone6的375像素宽的设备上,我们的html根元素font-size大小应该是50px,具体代码如下:

@media (min-width: 320px){html{font-size: 42.6667px;} }
@media (min-width: 360px){html{font-size: 48px;} }
@media (min-width: 375px){html{font-size: 50px;} }
@media (min-width: 384px){html{font-size: 51.2px;} }
@media (min-width: 414px){html{font-size: 55.2px;} }
@media (min-width: 448px){html{font-size: 59.7333px;} }
@media (min-width: 480px){html{font-size: 48px;} }
@media (min-width: 512px){html{font-size: 68.2667px;} }
@media (min-width: 544px){html{font-size: 72.5333px;} }
@media (min-width: 576px){html{font-size: 76.8px;} }
@media (min-width: 608px){html{font-size: 81.0667px;} }
@media (min-width: 640px){html{font-size: 85.3333px;} }
@media (min-width: 750px){html{font-size: 100px;} }

如此解决的话我们发现,一开始DOM还没有渲染完但可以正常展现的时候,html的根元素字体大小的设置来源于媒体查询,如下图;当DOM解析完成,js计算了html的根元素字体大小后,字体大小值来源于js设置的行内样式,计算后的值发挥作用!至此这个问题完美解决。

(请忽略背景图片没加载出来的问题哈)

扩展

到这个时候,你已经解决加载闪烁的问题了,但是运气不好的你还可能遇到一个问题,在某些设备上,会出现页面元素比期望值要小或者大,如下图,偷偷告诉你,这是设备系统字体大小的问题,详见下篇!rem布局在webview中页面错乱

补充 0925

如果你也好奇媒体查询的这些设备宽度节点哪里来的,有没有什么标准,那我会告诉你,我是在chrome的代码调试工具里找的,如下图,在箭头处找到 show media queries 就会显示啦。

当然除了显示媒体查询的节点,你还可以点击其他的选项看看,还有会有新发现的。比如可以显示手机外形,dpr等。是不是挺有意思的,快去试试吧!


反思 1024

碰巧今天是程序员节哈哈哈!

其实之前对这个解决方案一直不是很满意,我写了JS还要写一堆媒体查询,总感觉不对。

这两天我想了下,问题的原因无非就是html一开始没有设置字体大小嘛,那我们就一开始按最常用的iPhone 6 尺寸,设置html的font-size: 50px;好了,这样的话JS动态计算和媒体查询,我们只要选择一套方案就好了,他们两个是不同的适配方案,而且媒体查询的目的就是为了加载css的时候就设置html字体大小,我居然把他们混合起来使用,感觉有点冗余了。

有同学也会问了,设置html的font-size: 50px;就合理了吗?我的回答是,至少变化的范围非常小,以360px宽的设备为例,根字体大小应该是48px;以前相当于是从0px-48px,现在是50px-48px,不会造成很明显的闪烁问题。

至于为什么设置为50px;首先,设计稿是基于750px来设计的,我们重构稿实现的时候根元素大小应该是设置为50px(在规定1rem=100px的前提下);其次,720px和750px这两个设备尺寸,是安卓和IOS设备中占比比较大的设备尺寸。

最终方案: 
1.html{font-size: 50px;}//这个一定写 
2.JS动态计算和密集的媒体查询二选一

 

rem布局加载闪烁问题的更多相关文章

  1. android源码解析(十七)-->Activity布局加载流程

    版权声明:本文为博主原创文章,未经博主允许不得转载. 好吧,终于要开始讲讲Activity的布局加载流程了,大家都知道在Android体系中Activity扮演了一个界面展示的角色,这也是它与andr ...

  2. Android 如果布局中有ScrollView和Fragment或者带有滚动条的布局进行嵌套,布局加载完成页面无法定位到顶部的情况

    页面无法定位到顶部: 1.ScrollView中嵌套Fragment(Fragment中可能有想ScrollView,ListView带有滚动条的控件). 2.ScrollView嵌套ScrollVi ...

  3. Android View之布局加载流程

    1.引言 最近准备重新学习下Android,加深理解,快速形成自己的知识结构体系.最先学习的就算View部分,从自定义View到Activty层次结构,到layout加载过程.等等都会看一遍,在此记录 ...

  4. FrameWork内核解析之布局加载与资源系统(三)

    阿里P7Android高级架构进阶视频免费学习请点击:https://space.bilibili.com/474380680本篇文章将继续从以下两个内容来介绍布局加载与资源系统: [ LayoutM ...

  5. Android横竖屏切换及其对应布局加载问题

    第一,横竖屏切换连带横竖屏布局问题: 如果要让软件在横竖屏之间切换,由于横竖屏的高宽会发生转换,有可能会要求不同的布局. 可以通过以下两种方法来切换布局: 1)在res目录下建立layout-land ...

  6. vue 用v-if 或者 v-show 渲染dom时,初次加载闪烁的问题

    js 是等dom加载完成后操作的, 所以加载的时候,会闪烁. 此时,你会惊奇的发现,原来闪烁的dom或者文本 不闪烁了.

  7. vue解决加载闪烁问题

    <!DOCTYPE html><html> <head> <meta charset="utf-8"> <title>& ...

  8. angularjs中{{}} 加载出现闪烁问题

    在head标签中加入 [ng-cloak] { display: none !important; } 在页面的body标签上添加 ng-cloak 可以解决页面上先后加载闪烁问题

  9. Android 解决在初次打开Activity加载布局文件时,ScrollView滚动条不在顶部的问题

    出现这种问题的情况列举:ScrollView中嵌套有(包括自定义)的ListView,GridView时,会出现这种情况 解决办法: 1.在布局加载时让ScrollView上面的那个控件聚焦,具体做法 ...

随机推荐

  1. react中实现点击跳转到新页面方法

    实现点击跳转到新页面,可以有两种形式,一个是本地页面打开,一个是本地页面不变跳转到新的页面. (一)页面点击本地页面打开新页面 引入ant的Button组件 <Button style={{ba ...

  2. malloc创建三维数组

    #include <stdio.h> #include <stdlib.h> #include <malloc.h> int main() { //f[0],f[] ...

  3. PowerDesigner使用(设置继承,实现)

    1.File—New Mode 2添加4个class,1个接口(基本的添加工具都在这里面) 3.class1的设置名字,设置方法 3.设置继承,实现 4.编辑class2,class3继承父类的属性. ...

  4. mac burp suite https证书安装

    1. 下载burp suite 2.安装,设置并代理上 3. 打开http://burp并且下载证书 4. 点击打开选择始终信任并且导出桌面 5. 火狐打开设置至证书一栏[证书机构]导入切信任 6.大 ...

  5. IDEA下搜狗输入法输入中文时卡着不动的参考解决方法

    在IntelliJ IDEA工具的java编辑窗口,给代码增加注释时发现,输入中文时,搜狗输入法界面不动,一直卡着,如图:  我想输入“根据”两个字,但搜狗输入法界面一直卡着不刷新,导致都不知道自己输 ...

  6. 数据分析工具urule

    Python统计学书籍 https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w4004-13911786811.22.6431353b4F5iw1& ...

  7. win10重复安装

    使用大白菜启动盘装win10的时候,一直循环的重启然后设置,然后再重启,再设置.陷入了死循环. 解决办法:在自定义快捷键那个界面按 Ctrl+Shift+F3 .这是直接进入桌面的快捷键.

  8. ajax跨域原理以及jsonp使用

    jsonp介绍: JSONP(JSON with Padding)是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题. 由于同源策略,一般来说位于 server1.example. ...

  9. python---定义一个session类

    首先:注意cookie中的get_cookie是返回字符串,而get_secure_cookie返回的是字节类型 #self.get_secure_cookie() #The decoded cook ...

  10. 一个Entity Framework、ADO.NET查询性能测试

    Entity Framework自然是会比ADO.NET性能慢点,这个不多说了.直接上结果. 本该用测试项目的,不过我建了个aspx.下面是随便测20遍得到的结果 补充!!把12行改成 list = ...