为什么要使用rem 短命女 2021-06-26 16:06 456阅读 0赞 模仿网易移动端的的写法: html { font-size: 13.33333vw } @media screen and (max-width:320px) { html { font-size: 42.667px; font-size: 13.33333vw } } @media screen and (min-width:321px) and (max-width:360px) { html { font-size: 48px; font-size: 13.33333vw } } @media screen and (min-width:361px) and (max-width:375px) { html { font-size: 50px; font-size: 13.33333vw } } @media screen and (min-width:376px) and (max-width:393px) { html { font-size: 52.4px; font-size: 13.33333vw } } @media screen and (min-width:394px) and (max-width:412px) { html { font-size: 54.93px; font-size: 13.33333vw } } @media screen and (min-width:413px) and (max-width:414px) { html { font-size: 55.2px; font-size: 13.33333vw } } @media screen and (min-width:415px) and (max-width:480px) { html { font-size: 64px; font-size: 13.33333vw } } @media screen and (min-width:481px) and (max-width:540px) { html { font-size: 72px; font-size: 13.33333vw } } @media screen and (min-width:541px) and (max-width:640px) { html { font-size: 85.33px; font-size: 13.33333vw } } @media screen and (min-width:641px) and (max-width:720px) { html { font-size: 96px; font-size: 13.33333vw } } @media screen and (min-width:721px) and (max-width:768px) { html { font-size: 102.4px; font-size: 13.33333vw } } @media screen and (min-width:769px) { html { font-size: 102.4px; font-size: 13.33333vw } } 前几天看了下网易官网 `https://3g.163.com/touch/#/`,切到移动端视图,发现: ![在这里插入图片描述][20190819232609309.png]**它的css写的是`13.33vw`;** 再看看`css`文件,又发现: ![在这里插入图片描述][20190819232654791.png]依然写的都是`13.33vw`,那这个`13.33`是怎么来的呢? **如果你了解设计稿你就懂了,其实很简单:** 首先要先说明:移动端的设计稿一般是`width:750px,height:auto`(这里指的是不确定),`100vw = 100%`,这个也没有问题吧;那么,设计稿拿过来,我们可以得出:`750px = 100vw`,这个也没有问题吧,那么`1px`等于多少`vw`呢? 是不是 `1px = 100 / 750 vw = 0.133333vw`;那么`100px = 多少vw`呢,这个应该知道了吧。`100px = 13.33vw`; 思路过程: **`mobile.width = 750px => 750px = 100% =100vw => 750px = 100vw => 1px = 0.1333vw => 100px = 13.33vw => 1rem =100px;`** 即:我们把`html:{font-size: 13.33vw} // 也就是以100px位基准;1rem = 100px;` 现在就好算多了;`移动端的尺寸 / 100 = XXX rem;` 另外这个简单的js也能做出这样的效果: (function (window, document) { var getRem = function () { if (document) { var html = document.documentElement; var hWidth = (html.getBoundingClientRect().width) * (750 / 352); console.log(hWidth) html.style.fontSize = hWidth / 16 + "px"; console.log(html.style.fontSize) } }; getRem(); window.onresize = function () { getRem(); } })(window, document) ![在这里插入图片描述][20190819233151488.png] ![在这里插入图片描述][20190819233206521.png] -------------------- ## 以下是2019之前收集的资料: ## 之前有些适配做法,是通过`js`动态计算`viewport`的缩放值(`initial-scale`)。 例如以屏幕320像素为基准,设置1,那屏幕375像素就是375/320=1.18以此类推。 但直接这样强制页面缩放过于粗暴,会导致页面图片文字失真模糊。 `px`是相对固定单位,字号大小直接被定死,所以用户无法根据自己设置的浏览器字号而缩放,`em`和`rem`虽然都是相对单位,但em是相对于它的父元素的`font-size`,页面层级越深,`em`的换算就越复杂,而`rem`是直接相对于根元素,这就避开了很多层级关系。移动端新型浏览器对`rem`的兼容很好,可以放心使用。 ### 通用换算和一些坑 ### 有时我们会看到有些使用`rem`的页面里会先给页面根元素一个样式: html { font-size: 62.5%; /*10 ÷ 16 × 100% = 62.5%*/} 为什么是`62.5%`? 大多数浏览器的默认字号是`16px`,因此`1rem=16px`,这样不方便我们`px`和`rem`的换算,假设`1rem=10px`,那么`100px=10rem`,`25px=0.25rem`。这样就好换算很多,于是就有了上面的`10/16`。 如果是`640`的设计稿,需要除以`2`转化为和`iphone5`屏幕等宽的`320`。所以**设计稿`px`单位/2/10**转为`rem`。之后再媒体查询设置每个屏幕大小的`font-size`百分比,页面会根据上面设置的根`font-size`适配。 看到这里是不是觉得一切很完美?然而,这里面有两个深坑: 1. 我看了网上很多关于`rem`的资料,基本都说浏览器的默认字号就是`16px`,然后直接定义`font-size:62.5%`。但是,`rem`属于`css3`的属性,有些浏览器的早期版本和一些国内浏览器的默认字号并不是`16px`,那么上面的`10/16`换算就不成立,直接给`html`定义`font-size: 62.5%`不成立。 2. `chrome`强制字体最小值为`12px`,低于`12px`按`12px`处理,那上面的`1rem=10px`就变成`1rem=12px`,出现偏差(下面给demo)。 **解决方案: 将`1rem=10px`换为`1rem=100px`(或者其它容易换算的比例值);不要在`pc`端使用`rem`。** 那么上面的页面根元素样式要改为: html { font-size: 625%; /*100 ÷ 16 × 100% = 625%*/} 再用本工厂总结得出的各分辨率媒体查询换算: @media screen and (min-width:360px) and (max-width:374px) and (orientation:portrait) { html { font-size: 703%; } } @media screen and (min-width:375px) and (max-width:383px) and (orientation:portrait) { html { font-size: 732.4%; } } @media screen and (min-width:384px) and (max-width:399px) and (orientation:portrait) { html { font-size: 750%; } } @media screen and (min-width:400px) and (max-width:413px) and (orientation:portrait) { html { font-size: 781.25%; } } @media screen and (min-width:414px) and (max-width:431px) and (orientation:portrait){ html { font-size: 808.6%; } } @media screen and (min-width:432px) and (max-width:479px) and (orientation:portrait){ html { font-size: 843.75%; } } 至此,坑填完。**设计稿px换算直接/100即可得到`rem`值**。 ### 更精准健壮的换算 ### 然而,上面的625%大法除了有兼容性问题,也无法很好地根据不同设计稿精准适配,不是我们的最佳选择。网易和淘宝分别有自己的一套适配方法,适配性也很完美。 **网易手机端:** ![在这里插入图片描述][2019081923410511.png] ![在这里插入图片描述][20190819234135682.png]![在这里插入图片描述][20190819234147271.png] 基准值: 可以看到,无论页面以哪种手机比例缩放,`body`的`width`都是`7.5rem`。很明显,目前网易的手机端设计稿是基于`iPhone6`,`750`(设计师给的设计稿是物理分辨率,会是我们写样式的逻辑分辨率的两倍,如果给的设计稿是`640`,那么是基于`iPhone5`,`320`),且基准值是`100px`(`750/7.5=100`)。这个基准值很关键,后面的`css`换算,都和这个基准值有关。动态`font-size`: 我们看到图1、图2、图3的`font-size`都有根据屏幕大小而动态改变,可以推算出公式: 屏幕宽度/设计稿rem宽度=页面动态font-size值(如:375/7.5=50) 获取到这个值,再赋给`html`元素的`style`: document.documentElement.style.fontSize = document.documentElement.clientWidth / 7.5 + ‘px‘; 这样就设置好了每个页面的根`fonts-size`,因为`rem`单位是基于根`font-size`,因此只要确定一种设计稿对应手机的换算,其余屏幕尺寸均可自动适配。 上面我们得出设计稿换算`rem`的基准值是`100`,因此只需要把设计稿上的px值除以`100`即为我们要的`rem`值。 > `px/100=rem,所以100px=1rem,25px=0.25rem` **淘宝手机端: 大名鼎鼎的`Flexible`** 资料引用 [大漠:使用`Flexible`实现手淘H5页面的终端适配][Flexible_H5] [齐神:flexible解读及应用][flexible] 很多大神包括我们公司同事都有对此适配方案做了解析,所以我这边简单综述: **引入**: 直接引用阿里的`CDN`文件(或下载到本地引入) <script src="http://g.tbcdn.cn/mtb/lib-flexible/0.3.4/??flexible_css.js,flexible.js"></script> **设定**: 页面不要设定 。`Flexible`会自动设定每个屏幕宽度的根`font-size`、动态`viewport`、针对`Retina`屏做的`dpr`。 **换算**: 假设拿到的设计稿和上述网易的一样都是`750`,`Flexible`会把设计稿分为10份,可以理解为页面`width=10rem`,即`1rem=75px`,所以根`font-size`(基准值)=`75px`。 之后的`css`换算`rem`公式为: px/75=rem,所以100px=100/75=1.33rem,50px=50/75=0.66rem ### 换算工具 ### 显然,可以看出`px`与`rem`的换算因为基准值的不同而有些复杂,甚至需要借助计算器的辅助。在这里推荐一个换算神器:`cssrem` 安装好之后,做一些设置 * `px_to_rem` \- px转rem的单位比例,假设拿到设计稿750,基准值是75,此处就设75 * `max_rem_fraction_length` \- `px`转`rem`的小数部分的最大长度。默认为6。 * `available_file_types` \- **启用此插件的文件类型。`[".css", ".less", ".sass", ".scss"]`**。 ![技术分享][20190819235153388.png] ### 上述三种换算方案的步骤和优劣 ### **通用方案** 1、设置根`font-size:625%`(或其它自定的值,但换算规则`1rem`不能小于`12px`) 2、通过媒体查询分别设置每个屏幕的根`font-size` 3、css直接除以2再除以100即可换算为`rem`。 优:有一定适用性,换算也较为简单。 劣:有兼容性的坑,对不同手机适配不是非常精准;需要设置多个媒体查询来适应不同手机,单某款手机尺寸不在设置范围之内,会导致无法适配。 **网易方案** 1、拿到设计稿除以`100`,得到宽度`rem`值 2、通过给`html`的`style`设置`font-size`,把`1`里面得到的宽度`rem`值代入`x` document.documentElement.style.fontSize = document.documentElement.clientWidth / x + ‘px‘; 3、设计稿px/100即可换算为`rem` 优:通过动态根`font-size`来做适配,基本无兼容性问题,适配较为精准,换算简便。 劣:无`viewport`缩放,且针对`iPhone`的`Retina`屏没有做适配,导致对一些手机的适配不是很到位。 ## 网易`rem`方案: ## **前提**: <meta name="viewport" content="initial-scale=1,maximum-scale=1, minimum-scale=1"> **优势**: 不用管`DPR`,只需知设计稿宽度 **已知**: 假设现有`iPhone6`设计稿,宽`750px`,其中一元素宽`150px`; 根据`DPR`值,`iPhone6`的`DPR`值为`2`,我们可得其中该元素的显示尺寸: 真实显示CSS值: ![在这里插入图片描述][20190819235556311.png] 现在我们用网易方案来解决这个问题: 首先我们取`1rem = 100px`为参考值(这个值可以随便取,为何取这个值容后解答) 可知body的宽度: ![在这里插入图片描述][20190819235639314.png] 又因为body的宽度为`7.5rem`,由“网易公式”可得: Html的`font-size`为: ![在这里插入图片描述][20190819235703795.png] Dw为deviceWidth,即设备宽度,这是整个方案里唯一动态改变的值。 现我们已知设计稿为`iPhone6`,又知`iPhone6`的设备宽为`375px`, 这时候我们再回头看: `html`当前设备的`font-size`: ![在这里插入图片描述][20190819235742474.png] 且: ![在这里插入图片描述][20190819235803454.png] 可知,无形中这步已帮我们作了`DPR`换算;`750px`的设计稿,显示在`375px`的屏幕要怎样转换。 前面我们取了`1rem = 100px`,可得该元素宽:`150px = 1.5rem`, 又知\*\*`rem`为其他元素相对根元素(html)的大小,\*\* 所以可得当前元素宽度的真实css显示值为:`1.5rem*50px = 75px`;(这里的`75px`就跟我们前面理想得到的`75px`不谋而合了)。 这边我们把这个运算再拆解来看: ![在这里插入图片描述][20190819235914242.png]现再回头看:就可以知道为什么当时要取`100px`为参考值,取这个值的意义就是为了方便运算。 **总结**: 我们只需以**iPhone6**的设计稿(当前主导的机型),`750px`宽完成一套页面,当去到其他设备时,因为我们用的都是`rem`值,只需要通过`JS`动态获得当前的`dw`,再通过动态获取的`dw`改变`html`的`font-size`值,页面的其他元素也会因为`html`的改变而进行等比例缩放。 **步骤**: 1. 根据设计稿尺寸完成页面; 2. 设置`meta`,控制视口宽度,让页面以`1:1`比例渲染页面 3. 动态设置`html`的`font-size`; 4. 把各元素的px值除以`100`转换为`rem`(字体除外) **网易方案关键代码:** 设置视口: <meta name="viewport" content="initial-scale=1,maximum-scale=1, minimum-scale=1"> 动态设置`html`的`font-size`: document.documentElement.style.fontSize = document.documentElement.clientWidth / 7.5 + 'px'; ## 手淘方案 ## 1、拿到设计稿除以10,得到font-size基准值 2、引入`flexible` 3、不要设置`meta`的`viewport`缩放值 4、设计稿px/ font-size基准值,即可换算为rem 优:通过动态根`font-size、viewpor、dpr`来做适配,无兼容性问题,适配精准。 劣:需要根据设计稿进行基准值换算,在不使用`sublime text`编辑器插件开发时,单位计算复杂。 ## Demo ## 下面看看demo 设计稿:基于`iPhone5`,宽度`640`。 那么在开发模式,`iphone5`是`320`,所有数值均是设计稿一半大小。 期望效果:在`iPhone5`中,**box1宽高50px,box2宽高125px,字体15px**。其他屏幕终端自动适配。 ![技术分享][20190820000332978.png]**1、[62.5%方案][62.5]** 可以看出,基于chrome iPhone5的调试,box1宽高是60,box2宽高是150。出现了误差,就是上文提到字号最小值强制`12px`的原因。 **2、[625%方案][625]** 比例正常。 **3、[网易方案][Link 1]** 比例正常。 **4、[手淘方案][Link 2]** 比例正常(Retina屏做了缩放)。 **到底用哪种换算方案呢?** 每个人评判的标准不同。但个人更倾向`flexible`,动态计算`viewport`和针对`iphone`手机的`dpr`缩放使得页面适配更加精确,而且手淘页面用户访问量比网易页面大很多。 **移动端有用px的时候吗?** 有。当你的页面图片或者某一元素比例要固定,不想进行任何缩放时,`rem`就不适合了,这时候用`px`单位,能保证该元素不会因缩放而失真模糊。 [20190819232609309.png]: https://img-blog.csdnimg.cn/20190819232609309.png [20190819232654791.png]: /images/20210626/61df2d792dd847a1879ee49b2554e66f.png [20190819233151488.png]: /images/20210626/d6ab00d608b14bbea1883eb6710b3c99.png [20190819233206521.png]: /images/20210626/06d071c3a7a04f1ca32ede9aebdf0d5f.png [2019081923410511.png]: /images/20210626/19d76f67afb94930a079b954a1ddd298.png [20190819234135682.png]: https://img-blog.csdnimg.cn/20190819234135682.png [20190819234147271.png]: https://img-blog.csdnimg.cn/20190819234147271.png [Flexible_H5]: https://www.w3cplus.com/mobile/lib-flexible-for-html5-layout.html [flexible]: https://github.com/chesscai/flexible-adaptive [20190819235153388.png]: /images/20210626/4c904299eb5a49949d887db0ec005c5e.png [20190819235556311.png]: /images/20210626/a2fbb925fa134c8d863874520a251ef6.png [20190819235639314.png]: /images/20210626/beba51f1fe1448caad0d3f9ac75c269a.png [20190819235703795.png]: /images/20210626/94b5d61b942f4378ac0c722b032d1c88.png [20190819235742474.png]: /images/20210626/91e9de6520714c9492f19d06a89b9576.png [20190819235803454.png]: /images/20210626/a143cfb383d349678eaa288f108ffc3d.png [20190819235914242.png]: /images/20210626/23555c8049b942389ffd5d4803651a84.png [20190820000332978.png]: https://img-blog.csdnimg.cn/20190820000332978.png [62.5]: /images/20210626/468a1facfbd448359050ed8568855be5.png [625]: http://images.vrm.cn/2017/05/18/Rem2.html [Link 1]: http://images.vrm.cn/2017/05/18/Rem3.html [Link 2]: http://images.vrm.cn/2017/05/18/Rem4.html
还没有评论,来说两句吧...