移动端页面自适应解决方案— rem 布局篇

桂林seo半杯酒博客

移动端rem自适应方案

假设设计妹妹给我们的设计稿尺寸为750 * 1340。结合网易、淘宝移动端首页html元素上的font-size属性,html5设计稿尺寸以及前端与设计之间协作流程一般分为下面两种。

一、网易做法

引入:页面开头处引入下面这段代码,用于动态计算font-size

  1. (function(doc, win) {

  2. vardocEl = doc.documentElement,

  3. isIOS = navigator.userAgent.match(/(i[^;]+;( U;)? CPU.+Mac OS X/),

  4. dpr = isIOS ? Math.min(win.devicePixelRatio, 3) : 1,

  5. dpr = window.top === window.self? dpr : 1, //被iframe引用时,禁止缩放

  6. dpr = 1,

  7. scale = 1/ dpr,

  8. resizeEvt = 'orientationchange'inwindow ? 'orientationchange': 'resize';

  9. docEl.dataset.dpr = dpr;

  10. varmetaEl = doc.('meta');

  11. metaEl.name = 'viewport';

  12. metaEl.content = 'initial-scale='+ scale + ',maximum-scale='+ scale + ', minimum-scale='+ scale;

  13. docEl.firstElementChild.(metaEl);

  14. varrecalc = function() {

  15. varwidth = docEl.clientWidth;

  16. if(width / dpr > 750) {

  17. width = 750* dpr;

  18. }

  19. // 乘以100,px : rem = 100 : 1

  20. docEl.style.fontSize = 100* (width / 750) + 'px';

  21. };

  22. recalc()

  23. if(!doc.addEventListener) return;

  24. win.addEventListener(resizeEvt, recalc, false);

  25. })(document, window);

使用:

未引入前

  1. body {

  2. width: 750px;

  3. height: 640px;

  4. }

引入后:除以100并将px换成rem

  1. body {

  2. width: 7.5rem;

  3. height: 6.4rem;

  4. }

换算的依据:

  1. // 乘以100,px : rem = 100 : 1

  2. varrecalc = function() {

  3. varwidth = docEl.clientWidth;

  4. if(width / dpr > 750) {

  5. width = 750* dpr;

  6. }

  7. // 乘以100,px : rem = 100 : 1

  8. docEl.style.fontSize = 100* (width / 750) + 'px';

  9. };

二、淘宝做法

引入:页面开头处引入下面这段代码,用于动态计算font-size,或者单独放入一个文件,引入文件也可以

  1. ;

  2. (function(win, lib) {

  3. vardoc = win.document;

  4. vardocEl = doc.documentElement;

  5. varmetaEl = doc.querySelector('meta[name="viewport"]');

  6. varflexibleEl = doc.querySelector('meta[name="flexible"]');

  7. vardpr = 0;

  8. varscale = 0;

  9. vartid;

  10. varflexible = lib.flexible || (lib.flexible = {});

  11. if(metaEl) {

  12. varmatch = metaEl.getAttribute('content').match(/initial-scale=([d.]+)/);

  13. if(match) {

  14. scale = parseFloat(match[1]);

  15. dpr = parseInt(1/ scale);

  16. }

  17. } elseif(flexibleEl) {

  18. varcontent = flexibleEl.getAttribute('content');

  19. if(content) {

  20. varinitialDpr = content.match(/initial-dpr=([d.]+)/);

  21. varmaximumDpr = content.match(/maximum-dpr=([d.]+)/);

  22. if(initialDpr) {

  23. dpr = parseFloat(initialDpr[1]);

  24. scale = parseFloat((1/ dpr).toFixed(2));

  25. }

  26. if(maximumDpr) {

  27. dpr = parseFloat(maximumDpr[1]);

  28. scale = parseFloat((1/ dpr).toFixed(2));

  29. }

  30. }

  31. }

  32. if(!dpr && !scale) {

  33. varisAndroid = win.navigator.appVersion.match(/android/gi);

  34. varisIPhone = win.navigator.appVersion.match(/iphone/gi);

  35. vardevicePixelRatio = win.devicePixelRatio;

  36. if(isIPhone) {

  37. // iOS下,对于2和3的屏,用2倍的方案,其余的用1倍方案

  38. if(devicePixelRatio >= 3&& (!dpr || dpr >= 3)) {

  39. dpr = 3;

  40. } elseif(devicePixelRatio >= 2&& (!dpr || dpr >= 2)) {

  41. dpr = 2;

  42. } else{

  43. dpr = 1;

  44. }

  45. } else{

  46. // 其他设备下,仍旧使用1倍的方案

  47. dpr = 1;

  48. }

  49. scale = 1/ dpr;

  50. }

  51. docEl.setAttribute('data-dpr', dpr);

  52. if(!metaEl) {

  53. metaEl = doc.('meta');

  54. metaEl.setAttribute('name', 'viewport');

  55. metaEl.setAttribute('content', 'initial-scale='+ scale + ', maximum-scale='+ scale + ', minimum-scale='+ scale + ', user-scalable=no');

  56. if(docEl.firstElementChild) {

  57. docEl.firstElementChild.(metaEl);

  58. } else{

  59. varwrap = doc.('p');

  60. wrap.(metaEl);

  61. doc.write(wrap.innerHTML);

  62. }

  63. }

  64. functionrefreshRem() {

  65. varwidth = docEl.getBoundingClientRect().width;

  66. // 适配平板

  67. if(width / dpr > 540) {

  68. width = 540* dpr;

  69. }

  70. varrem = width / 10;

  71. docEl.style.fontSize = rem + 'px';

  72. flexible.rem = win.rem = rem;

  73. }

  74. win.addEventListener('resize', function() {

  75. clearTimeout(tid);

  76. tid = setTimeout(refreshRem, 300);

  77. }, false);

  78. win.addEventListener('pageshow', function(e) {

  79. if(e.persisted) {

  80. clearTimeout(tid);

  81. tid = setTimeout(refreshRem, 300);

  82. }

  83. }, false);

  84. if(doc.readyState === 'complete') {

  85. doc.body.style.fontSize = 12* dpr + 'px';

  86. } else{

  87. doc.addEventListener('DOMContentLoaded', function(e) {

  88. doc.body.style.fontSize = 12* dpr + 'px';

  89. }, false);

  90. }

  91. refreshRem();

  92. flexible.dpr = win.dpr = dpr;

  93. flexible.refreshRem = refreshRem;

  94. flexible.rem2px = function(d) {

  95. varval = parseFloat(d) * this.rem;

  96. if(typeofd === 'string'&& d.match(/rem$/)) {

  97. val += 'px';

  98. }

  99. returnval;

  100. }

  101. flexible.px2rem = function(d) {

  102. varval = parseFloat(d) / this.rem;

  103. if(typeofd === 'string'&& d.match(/px$/)) {

  104. val += 'rem';

  105. }

  106. returnval;

  107. }

  108. })(window, window['lib'] || (window['lib'] = {}));

使用:

未引入前

  1. body {

  2. width: 750px;

  3. height: 640px;

  4. }

引入后

  1. @font-size-base: 75;

  2. body {

  3. width: 750rem/@font-size-base;

  4. height: 640rem/@font-size-base;

  5. }

换算依据:

  1. functionrefreshRem() {

  2. varwidth = docEl.getBoundingClientRect().width;

  3. // 适配平板

  4. if(width / dpr > 540) {

  5. width = 540* dpr;

  6. }

  7. varrem = width / 10;

  8. docEl.style.fontSize = rem + 'px';

  9. flexible.rem = win.rem = rem;

  10. }

这边是用的less,如果您没有用less,就需要手动计算,当然也可以转化为px : rem = 100 : 1。如果想转化为px : rem = 100 : 1,可以修改上面的refreshRem函数:

  1. functionrefreshRem() {

  2. varwidth = docEl.getBoundingClientRect().width

  3. // 适配平板

  4. if(width / dpr > 750) {

  5. width = 750* dpr

  6. }

  7. varrem = 100* (width / 750)

  8. docEl.style.fontSize = rem + 'px'

  9. flexible.rem = win.rem = rem;

  10. }

使用:

未引入前

  1. body {

  2. width: 750px;

  3. height: 640px;

  4. }

引入后:除以100并将px换成rem

  1. body {

  2. width: 7.5rem;

  3. height: 6.4rem;

  4. }

换算依据就是上面修改的代码:

  1. functionrefreshRem() {

  2. varwidth = docEl.getBoundingClientRect().width

  3. // 适配平板

  4. if(width / dpr > 750) {

  5. width = 750* dpr

  6. }

  7. varrem = 100* (width / 750)

  8. docEl.style.fontSize = rem + 'px'

  9. flexible.rem = win.rem = rem;

  10. }

希望对需要的朋友有所帮助!