Webpack5之px自动转换成rem

Posted IT人.阿标

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Webpack5之px自动转换成rem相关的知识,希望对你有一定的参考价值。

文章目录

背景介绍

相信有过开发经验的同学都知道,无论你是做iosandroid,还是前端开发,在做页面适配的话,都需要视频各种尺寸大小的屏幕。在传统的开发过程中,想要去适配不同大小的屏幕需要使用媒体查询实现@media screen and,这样一来适配多少个屏幕就需要编写多少个适配代码,无端添加工作量,切维护困难。

为了结局上面地问题CSS3新增了一个相对单位rem。

W3C 对 rem 的定义: font-size of the root element

  • rem 是相对单位
  • px 是绝对单位

移动端 CSS px 自动转换成 rem

使用步骤:

  1. 插件安装
npm i -D px2rem-loader
npm i -S lib-flexible    #页面渲染时计算根元素的 font-size 值
  1. 手动添加flexible

    找到node_modules\\lib-flexible\\flexible.js,复制到目标文件里面

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>Webpack App</title>
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <script type="text/javascript">
    
            ;(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('将根据已有的meta标签来设置缩放比例');
                    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下,对于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 
                        // 其他设备下,仍旧使用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'] = ));
        </script>
    </head>
    
    <body>
    <div class="box">
        hello box
    </div>
    </body>
    </html>
    

    注意flexible.js复制到目标文件的时候,标签一定要放到前面,不能通过link方式引入,应为界面加载完成以后,需要立即计算html的font-size。

  2. 配置文件webpack.config.js配置

      module: 
        rules: [
          
            test: /\\.less$/,
            use: [
              // 'style-loader',
              MiniCssExtractPlugin.loader,
              'css-loader',
              'less-loader',
              
                loader: "postcss-loader",
                options: 
                  postcssOptions: 
                    plugins: [autoprefixer(
                      overrideBrowserslist: [
                        'last 10 Chrome versions',
                        'last 5 Firefox versions',
                        'Safari >= 6',
                        'ie> 8'
                      ]
                    )]
                  
    
                
              ,
              
                loader: 'px2rem-loader',
                options: 
                  remUnit: 75,
                  remPrecision: 8
                
              
            ]
          
        ]
      ,
    

注意:如果在css文件里,某些px不需要转化为rem,需要在改行后面加上/*no*/ 这种注释语法会不进行 rem 的转换,如:

.search-text 
  font-size: 43px;
  width: 200px; /* no */

转化后的效果。所有的px都转化为了rem

body 
    color: green;

.box 
  font-size: 0.44rem;
  color: red;
  border-radius: 0.2rem;
  background: aqua;
  padding-left: 0.13333333rem;
  display: -webkit-box;
  display: -webkit-flex;
  display: -ms-flexbox;
  display: flex;
  -webkit-transition: -webkit-transform 1s;
  transition: -webkit-transform 1s;
  transition: transform 1s;
  transition: transform 1s, -webkit-transform 1s;

以上是关于Webpack5之px自动转换成rem的主要内容,如果未能解决你的问题,请参考以下文章

Webpack5之px自动转换成rem

vue px转换为rem

vue 手机端H5单位px自动转换成rem

VSCode编程工具小插件之px一键转换成rem

H5在移动端尺寸适配方案

vue项目屏幕适配帮我们自动将px单位转换成rem单位