如果你看了很多篇文章,对 flexible 的解决方案一直还有一种不太了解的朦胧感觉,那么这篇文章会帮你从背景角度一步一步解析为何会有 flexible 这套解决方案,以及这套解决方案是如何作用的。
设计师基于 iphone6(375px 逻辑像素) 的页面尺寸给了你一个非常简单的设计稿
你很快用如下的代码实现了,在 chrome 控制台打开 iphone6 查看效果,和设计稿丝毫不差。
<div class="box1"></div>
<div class="box2"></div>
<style>
.box1 {
width: 100px;
height: 100px;
border: 1px solid red;
position: fixed;
left: 10px;
}
.box2 {
width: 100px;
height: 100px;
border: 1px solid red;
position: fixed;
right: 10px;
}
</style>
但是选则机型为 iphone5 时页面变成了这个样子。
会发现在 iphone5 的页面下两个方块的间距和方块大小比起来变得非常小,这样我们认为这个网页在不同屏幕尺寸的手机上产生了不同的显示效果。
这个时候肯定有同学说了,那这个设计图我用 vw 去还原就好了。的确使用 vw 还原设计图是可以做到的,但 vw 目前的兼容性仍然有问题,测试很可能甩过来一个 vivo-x7 告诉你页面乱掉了。
设计师在 375px ( iphone6 逻辑像素宽度 ) 的页面上画出了这个设计图,则该 100px 的方块在不同尺寸的手机上的大小实际应该为 (100px/375px)*{屏幕逻辑像素宽度},然而我们不可能为每一种尺寸都在 css 上写一个 px 宽度。这时可以使用 rem,我们可以通过设置根节点的 font-size 来使不同尺寸的手机的 1rem 对应的 px 值不同。
上面的话读起来很绕,我写起来很绕,那么我将 100px 在 iphone5 和 iphone6 上的不同数值列个表
手机型号 | 逻辑像素宽度 | 根节点 font-size | rem 数值 | px 数值 |
---|---|---|---|---|
iphone5 | 320 px | 64 px | (100/75) rem | (100/75)*64 px |
iphone6 | 375 px | 75 px | (100/75) rem | (100/75)*75 px |
这样在 iphone6 的屏幕尺寸上以 100px 渲染出来的盒子大小才能在 iphone5 的屏幕尺寸上以相同的比例渲染出来,在 iphone5 上渲染宽度为 (100/75)*64px == 85.33px,所以 flexible 的源码中refreshRem函数就是在计算不同手机尺寸应当设置的根节点 font-size,如下所示。
function refreshRem() {
var width = docEl.getBoundingClientRect().width
if (width / dpr > 540) {
// 这里是为了适配 ipad 和 android 平板横屏的情况(请暂时无视这个 if 语句)
width = 540 * dpr
}
var rem = width / 10 // 将屏幕宽度分为 10 份,每份为 1rem
docEl.style.fontSize = rem + 'px'
flexible.rem = win.rem = rem
}
如果读这篇文章同学在之前有读过其他地方的文章会认为我上面的解释是错误的,因为其他的文章在上面均使用的屏幕物理像素作为基准,并配合设置 <viewport content="width=device-width,user-scalable=no,initial-scale=${scale}"> 实现,其实,如果没有 1px 像素的问题是不需要设置 initial-scale 的。在文章的前半部分着重讲解了如何用 rem 实现类似 vw 的效果,下面是关于 1px 像素问题的来龙去脉。
首先需要区分 物理像素 和 逻辑像素,物理像素即为显示器上的最小显示单元,逻辑像素也就是 css 像素,是在网页上渲染时的最小单位。而物理像素与逻辑像素之比 (物理像素/逻辑像素) 称之为 dpr (device pixel ratio),iphone 5的物理像素宽度为 640px,逻辑像素宽度为 320px,则 iphone5 的 dpr 为 2。意味着在 css 上写 1px 的宽度,在 iphone5 的显示屏幕上实际渲染了 2px 的物理像素,使得我们在 dpr>=2 的手机上设置 border-width:1px 看起来非常的粗。
为了解决这个问题,flexible对上面的方案进行了优化。将 initial-scale 设置为 1/dpr,这样 dpr 为 2 的手机就会将页面缩小至 1/2 显示,这个时候设置 border-width:1px 就真的是 1px 物理像素。但是不能因为这个修改影响其他地方的布局,其实解决方案也很简单,就是将根节点的 font-size = font-size * dpr ,来将布局大小放大回正常的样子(但实际不是这样写的,是因为当设置了 scale = 1/2 时,documentn.documentElement.getBoundingClientRect().width 取得逻辑像素值会增大至 2 倍,所以不需要额外进行 根节点的 font-size = font-size * dpr)。
var width = docEl.getBoundingClientRect().width
var rem = width / 10 // 将屏幕宽度分为 10 份,每份为 1rem
docEl.style.fontSize = rem + 'px'
在 flexible 中有这样一行代码 docEl.setAttribute('data-dpr', dpr);这样我们可以在自己的 css 中根据data-dpr来设置不同 dpr (可以理解为页面缩放比例) 下的字体大小
[data-dpr='1'] .text{
font-size: 12px;
}
[data-dpr='2'] .text{
font-size: 24px;
}
[data-dpr='3'] .text{
font-size: 36px;
}
在你的浏览器中打开这段代码并在移动端不同机型上进行切换,会得到正确的设计图还原效果。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script type="text/javascript" src="http://g.tbcdn.cn/mtb/lib-flexible/0.3.2/??flexible_css.js,flexible.js">
</script>
<title>Document</title>
</head>
<body>
<div class="box1"></div>
<div class="box2"></div>
<style>
.box1 {
width: 2.666666666666667rem; // 100px ÷ 37.5px(375px设计稿上的根 font-size 大小) = 2.666666666666667rem ,使用 css 预处理器的可以写一个函数
height: 2.666666666666667rem;
border: 1px solid red;
position: fixed;
left: 0.2666666666666667rem;
top: 0.2666666666666667rem;
}
.box2 {
width: 2.666666666666667rem;
height: 2.666666666666667rem;
border: 1px solid red;
position: fixed;
right: 0.2666666666666667rem;
top: 0.2666666666666667rem;
}
</style>
</body>
</html>
希望看完这篇文章的你,再去这里再好好看一下源码的实现细节部分:flexible 源码
目前,随着移动设备的普及和4G网络的普及,web在移动端的占比已经远远超过PC端,各种H5页面推广页面,H5小游戏热度火爆。以前简单的使用px单位(没有弹性)的时代已经无法满足各位设计师和用户了
rem可以理解为一个长度单位,单位rem的值等于网页font-size的值。如果网页的字体大小为默认值16px,那么1rem就等于16px,0.5rem等于8px。根据这个原理,如果网页默认的字体大小改变,那么单位rem的大小也会改变
1:css3的media query来实现适配,例如下面这样;2.通过js动态设置html字体,例如下面这样:默认设计图为640的情况下1rem=100px;根据自己需求修改
规则就是,调用函数,放两个参数,第一个参数,是设计稿的宽度,第二个参数是px与rem的转换比例,通常会写100(因为好算);当然了,要把这段js代码最好封装在一个单独的js文件里,并且放在所有的css文件引入之前加载
最近在学习小程序,要把html的代码转换成小程序界面,其中就遇到了rem的转换问题,但小程序不太兼容rem,不是不能用rem,而是没办法设置根元素的font-size,因为rem是相对于根元素的font-size
根据设计稿的实际宽度值,与设计稿最大宽度值,动态计算根字体大小,适应不同的屏幕比例。本文的px转rem换算公式为:100px = 1rem
针对近日华为,小米的部分机型,在升级系统或升级微信之后,微信内置浏览器产生的rem不能正确填充满的问题,有如下解决方案,目前来看,产生这个情况的原因是因为给html附font-size时
rem是CSS3中新增加的一个单位值,他和em单位一样,都是一个相对单位。不同的是em是相对于元素的父元素的font-size进行计算;rem是相对于根元素html的font-size进行计算。rem 和 em 一样,也是一个相对大小的值,它是相对于根元素 <html>。
今天我们深度了解一下 rem 单位,这个单位目前已经得到了优秀浏览器的支持,并且有一些兼容方案来帮助你在低版本的 IE 浏览器中的使用它。
rem是相对于根元素<html>,这样就意味着,我们只需要在根元素确定一个px字号,则可以来算出元素的宽高。本文讲的是如何使用rem实现自适应。 rem这是个低调的css单位,近一两年开始崭露头角
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!