關(guān)于 Rem 的適配!前端頁(yè)面響應(yīng)式開發(fā)必備技巧
本文轉(zhuǎn)載自微信公眾號(hào)「零零后程序員小三」,作者003 。轉(zhuǎn)載本文請(qǐng)聯(lián)系零零后程序員小三公眾號(hào)。
哈嘍大家好我是小三,作為全棧工程師當(dāng)然是要了解前端的東西。最近學(xué)到了rem,分享下學(xué)習(xí)的心得。
我們作為前端初學(xué)者來(lái)說(shuō),是不是有一個(gè)疑惑,我們電腦屏幕大,但是手機(jī)屏幕小,那我在PC端頁(yè)面寫好的東西到了手機(jī)端豈不是很難看?
所以!我在這里將會(huì)給你們介紹關(guān)于rem的適配方案
關(guān)于rem的適配方案?
- 「適配的目的是什么?」
- 「原理是什么」
- 「怎么做?」
帶著這三個(gè)疑問(wèn),我們一起來(lái)看看rem
適配的目的是什么?
肯定是為了適應(yīng)在不同的設(shè)備下,我們寫出來(lái)的效果差別不大,如果我們只按照PC端來(lái)開發(fā),如果用戶用手機(jī)打開這個(gè)頁(yè)面,那肯定是用起來(lái)很難受。
而且,如果我們?yōu)榱巳ミm配某一臺(tái)手機(jī),而再去寫一個(gè)樣式,那豈不是工作量更大,更何況市面上的手機(jī)品類這么多,屏幕大小不一,什么劉海屏什么的,那工作量可想而知!
原理是什么
我們這就來(lái)看看。實(shí)現(xiàn)rem的原理是什么?
「一. 根據(jù)UI給我們的設(shè)計(jì)稿與設(shè)備寬度的大小比例,動(dòng)態(tài)的計(jì)算然后去設(shè)置html的字體大小(font-size);然后頁(yè)面大小根據(jù)一個(gè)公式去規(guī)范元素的大小」
「二. 根據(jù)設(shè)計(jì)稿元素的寬,高的取值,根據(jù)同比例換算為rem單位的值」
怎么做?
首先,我們以iphone6為例子,因?yàn)槲覀兂S瞄_發(fā)都是以iphone6作為移動(dòng)端的例子來(lái)?yè)Q算,這里為什么就需要您們自己去百度了。
less + @media(媒體查詢) + rem
我們假設(shè)UI給我們的設(shè)計(jì)稿是750px的,然后呢我們把屏幕劃分為15等份(看個(gè)人需求,15到20等份也是可以的),然后每一份作為HTML的文字大小,然后750除以15也就是50px,那么當(dāng)我們?cè)趯挾葹?75px的設(shè)備的時(shí)候,字體大小的換算就是375除上15等分,算出結(jié)果25px,然后用頁(yè)面元素的大小除以不同HTML字體大小,你會(huì)發(fā)現(xiàn)比例還是一樣的,
比如一個(gè)100乘100像素大小的盒子在750屏幕下,就是100除以50轉(zhuǎn)換為rem的話是2rem乘2rem,
再比如,當(dāng)我們想在375的屏幕下畫一個(gè)100px的盒子,那就是4rem乘4rem
然后我們看看代碼
- <head>
- <meta charset="UTF-8" />
- <meta http-equiv="X-UA-Compatible" content="IE=edge" />
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
- <title>Document</title>
- <style>
- @media screen and (min-width: 375px) {
- html {
- font-size: 25px;
- }
- }
- @media screen and (min-width: 750px) {
- html {
- font-size: 50px;
- }
- }
- .box1 {
- width: 2rem;
- height: 2rem;
- background-color: green;
- }
- .box2 {
- width: 4rem;
- height: 4rem;
- background-color: skyblue;
- }
- </style>
- </head>
- <body>
- <div class="box1"></div>
- <div class="box2"></div>
- </body>
我們先看看750屏幕
再看看375的移動(dòng)端
然后可以發(fā)現(xiàn)
100乘100 px元素在750屏幕下 就是100/50 轉(zhuǎn)換為rem 是2rem2rem 比例是 1比1
375屏幕下 html字體大小為25 則2rem=50px 此時(shí)寬和高都是50 但比例還是1比1
最后得出公式:
設(shè)計(jì)稿寬值也就是頁(yè)面元素值=A =>(已知)
html的字體大小值=B
劃分的份數(shù)=C =>(已知)
rem的值 = X
X = A / B / C
B = A / C
@media +flexble.js + rem
使用flexible.js能輕松搞定各種不同的移動(dòng)端設(shè)備兼容自適應(yīng)問(wèn)題。
用起來(lái)也是特別的簡(jiǎn)單,我們只需要引入這個(gè)東西,原理還是將設(shè)備劃分等份 不同的設(shè)備 比例還是一致的
然后自己需求設(shè)置屏幕大小,我的是這樣的
- <head>
- <meta charset="UTF-8" />
- <meta http-equiv="X-UA-Compatible" content="IE=edge" />
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
- <title>Document</title>
- <scri src="./flexible/flexible.js"></script>
- <style>
- @media screen and (min-width: 375px) {
- html {
- font-size: 25px;
- }
- }
- @media screen and (min-width: 750px) {
- html {
- font-size: 50px;
- }
- }
- div {
- width: 2rem;
- height: 2rem;
- background-color: rgb(247, 5, 5);
- }
- </style>
- </head>
- <body>
- <div></div>
- </body>
下面是我去網(wǎng)上查找到的js文件,需要的可以自行下載使用
- (function(win, lib) {
- var doc = win.document;
- var docEl = doc.documentElement;
- var metaEl = doc.querySelector('meta[name="viewport"]');
- var flexibleEl = doc.querySelector('meta[name="flexible"]');
- var dpr = 0;
- var scale = 0;
- var tid;
- var flexible = lib.flexible || (lib.flexible = {});
- if (metaEl) {
- console.warn('將根據(jù)已有的meta標(biāo)簽來(lái)設(shè)置縮放比例');
- var match = metaEl.getAttribute('content').match(/initial-scale=([\d.]+)/);
- if (match) {
- scale = parseFloat(match[1]);
- dpr = parseInt(1 / scale);
- }
- } else if (flexibleEl) {
- var content = flexibleEl.getAttribute('content');
- if (content) {
- var initialDpr = content.match(/initial-dpr=([\d.]+)/);
- var maximumDpr = content.match(/maximum-dpr=([\d.]+)/);
- if (initialDpr) {
- dpr = parseFloat(initialDpr[1]);
- scale = parseFloat((1 / dpr).toFixed(2));
- }
- if (maximumDpr) {
- dpr = parseFloat(maximumDpr[1]);
- scale = parseFloat((1 / dpr).toFixed(2));
- }
- }
- }
- if (!dpr && !scale) {
- var isAndroid = win.navigator.appVersion.match(/android/gi);
- var isIPhone = win.navigator.appVersion.match(/iphone/gi);
- var devicePixelRatio = win.devicePixelRatio;
- if (isIPhone) {
- // iOS下,對(duì)于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 {
- // 其他設(shè)備下,仍舊使用1倍的方案
- dpr = 1;
- }
- scale = 1 / dpr;
- }
- docEl.setAttribute('data-dpr', dpr);
- if (!metaEl) {
- metaEl = doc.createElement('meta');
- metaEl.setAttribute('name', 'viewport');
- metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
- if (docEl.firstElementChild) {
- docEl.firstElementChild.appendChild(metaEl);
- } else {
- var wrap = doc.createElement('div');
- wrap.appendChild(metaEl);
- doc.write(wrap.innerHTML);
- }
- }
- function refreshRem() {
- var width = docEl.getBoundingClientRect().width;
- if (width / dpr > 540) {
- width = 540 * dpr;
- }
- var rem = width / 10;
- docEl.style.fontSize = rem + 'px';
- flexible.rem = win.rem = rem;
- }
- win.addEventListener('resize', function() {
- clearTimeout(tid);
- tid = setTimeout(refreshRem, 300);
- }, false);
- win.addEventListener('pageshow', function(e) {
- if (e.persisted) {
- clearTimeout(tid);
- tid = setTimeout(refreshRem, 300);
- }
- }, false);
- if (doc.readyState === 'complete') {
- doc.body.style.fontSize = 12 * dpr + 'px';
- } else {
- doc.addEventListener('DOMContentLoaded', function(e) {
- doc.body.style.fontSize = 12 * dpr + 'px';
- }, false);
- }
- refreshRem();
- flexible.dpr = win.dpr = dpr;
- flexible.refreshRem = refreshRem;
- flexible.rem2px = function(d) {
- var val = parseFloat(d) * this.rem;
- if (typeof d === 'string' && d.match(/rem$/)) {
- val += 'px';
- }
- return val;
- }
- flexible.px2rem = function(d) {
- var val = parseFloat(d) / this.rem;
- if (typeof d === 'string' && d.match(/px$/)) {
- val += 'rem';
- }
- return val;
- }
- })(window, window['lib'] || (window['lib'] = {}));