网页的自适应布局和px转rem方案

作者: 北风吹_yfy | 来源:发表于2020-02-14 16:02 被阅读0次

    一、CSS3 Media Queries

    • Media Queries定义
      其作用就是允许添加表达式用以确定媒体的环境情况,以此来应用不同的样式表。(换句话说,其允许我们在不改变内容的情况下,改变页面的布局以精确适应不同的设备。 )
    • 使用方式(两种)
    1. 方式一:直接在link中判断设备的尺寸,然后引用不同的css文件:
    // 当屏幕的宽度大于600小于800时,应用styleB.css
     <link rel="stylesheet" type="text/css" href="styleB.css"  media="screen and (min-width: 600px) and (max-width: 800px)">
    
    在media属性里:
    (1)screen 是媒体类型里的一种,CSS2.1定义了10种媒体类型;
    (2)and 被称为关键字,其他关键字还包括 not(排除某种设备),only(限定某种设备);
    (3)(min-width: 400px) 就是媒体特性,其被放置在一对圆括号中。
    
    1. 方式二:即是直接写在<style>标签里:
    @media screen and (max-width: 600px) { /*当屏幕尺寸小于600px时,应用下面的CSS样式*/
          .class {
              background: #ccc;
           }          
      }
    

    写法是前面加@media,其它跟link里的media属性相同。

    其实基本上就是样式覆盖~,判断设备,然后引用不同的样式文件覆盖。 
    要注意的是由于网页会根据屏幕宽度调整布局,所以不能使用绝对宽度的布局,也不能使用具有绝对宽度的元素。这一条非常重要,否则会出现横向滚动条。
    

    二、calc()

    calc()使用通用的数学运算规则,但是也提供更智能的功能:

    >使用“+”、“-”、“*” 和 “/”四则运算;
    >可以使用百分比、px、em、rem等单位;
    >可以混合使用各种单位进行计算;
    >表达式中有“+”和“-”时,其前后必须要有空格,如"widht: calc(12%+5em)"这种没有空格的写法是错误的;
    >表达式中有“*”和“/”时,其前后可以没有空格,但建议留有空格。
    
    例如 :设置div元素的高度为当前窗口高度-80px
     div{
       height: calc(100vh - 80px);     
    }
    或者利用%计算宽度
    如: width: calc(100% - 10px);
    

    vw Viewport宽度, 1vw 等于viewport宽度的1%
    vh Viewport高度, 1vh 等于viewport高的的1%

    三、rem

    在JS引入rem,动态改变html的font-size。用rem动态改变字体大小:

    ;(function(win) {
        var tid;
        function refreshRem() {
            let designSize = 1920; // 设计图尺寸
            let html = document.documentElement;
            let wW = html.clientWidth;// 窗口宽度
            let rem = wW * 100 / designSize; 
            document.documentElement.style.fontSize = rem + 'px';
        }
        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);
        refreshRem();
    })(window);
    

    四、px 转 rem 方案

    • less,sass,stylus三种预处理器px2rem
    1. less
     //定义一个变量和一个mixin
     @baseFontSize: 75;//基于视觉稿横屏尺寸/100得出的基准font-size
     .px2rem(@name, @px){
         @{name}: @px / @baseFontSize * 1rem;
     }
    
    //使用示例:
    .container {
       .px2rem(height, 240);
    }
    
    //less翻译结果:
    .container {
       height: 3.2rem;
    }
    
    1. sass
    //定义一个变量和一个mixin
    $baseFontSize: 16;//默认基准font-size
    @mixin px2rem($name, $px){
      #{$name}: $px / $baseFontSize * 1rem;
    }
     
    // 使用示例:
     .container {
       @include px2rem(height, 240);
     }
     
    //  scss翻译结果:
      .container {
        height: 3.2rem;
      }
    
    1. stylus
    //定义一个变量和一个mixin
    $baseFontSize = 16; //默认基准font-size
    px2rem(name, px){
    {name}: px / $baseFontSize * 1rem;
    }
     
    // 使用示例:
    .container {
      px2rem('height', 240);
    }
     
    //  stylus翻译结果:
    .container {
      height: 3.2rem;
    }
    

    建议将mixin放入单独文件夹下,例如webpack中的common,之后使用只需要在style中引入,以scss为例:

    @import "../common/scss/mixin.scss";
     
      .all {
        @include px2rem(padding, 32);
      }
    
    • flexible插件
      此处案例属于vue项目中引用
    1. 安装
    npm i lib-flexible --save
    

    2.引入lib-flexible
    在main.js中引入lib-flexible:

    import 'lib-flexible'
    
    1. 使用px2rem-loader自动将css中的px转换成rem
    • 安装px2rem-loader:
    npm install px2rem-loader --save-dev
    
    • 配置px2rem-loader:
      (1)打开build/utils.js文件,找到exports.cssLoaders方法,在里面添加如下代码:
    const px2remLoader = {
        loader: 'px2rem-loader',
        options: {
          remUint: 75,  //设计稿宽度/10, 以设计稿750为例, 750 / 10 = 75
        }
      }
    

    (2)打开build/utils.js文件,找到generateLoaders方法, 添加px2remLoader 插件:

    function generateLoaders (loader, loaderOptions) {
       const loaders = options.usePostCSS ? [cssLoader, postcssLoader, px2remLoader] : [cssLoader, px2remLoader]
    
       if (loader) {
         loaders.push({
           loader: loader + '-loader',
           options: Object.assign({}, loaderOptions, {
             sourceMap: options.sourceMap
           })
         })
       }
    //...
    

    (3)build/utils.js文件 添加 generateSassResourceLoader方法:

    function generateSassResourceLoader () {                
           const loaders = [
              cssLoader,
              px2remLoader,
              'less-loader'
           ]
           if (options.extract) {
              return ExtractTextPlugin.extract({
                 use: loaders,
                 fallback: 'vue-style-loader'
              })
           } else {
               return ['vue-style-loader'].concat(loaders)
           }
        }
    

    (4)修改 build/utils.js文件 return

    return {
         css: generateLoaders(),
         postcss: generateLoaders(),
         less: generateSassResourceLoader()                //  修改less的值
    } 
    
    • 如果是大屏需要修改flexible源码
      打开./node_modules/lib-flexible/flexible.js,找到如下片段源码:
    function refreshRem(){
        var width = docEl.getBoundingClientRect().width;
        if (width / dpr > 540) {
            width = width * dpr;
        }
        var rem = width / 10;
        docEl.style.fontSize = rem + 'px';
        flexible.rem = win.rem = rem;
    }
    
    • 重启,完成
      修改完成后,重启项目,则会适配到相应的尺寸。此外还有一个提示,当脱离掉node_modules重新npm install项目依赖时还是需要重新修改一遍的,千万别忘了!
    • 为解决重新安装依赖需要再次配置,按以下方法:
      先把flexible.js源码文件拷贝到项目下,然后修改改文件,此处提到了src文件下,然后需要修改main.js里的引入路劲:
    import './flexible'
    

    此处在提出的文件如出现eslint报错问题,可在文件顶部加上/* eslint-disable */即可。

    • 问题1:1px的边框也会帮你转成rem。
    //对于有些地方不用转换的我们可以在样式后面添加/*no*/这样就不会给我们转化了;
    .box{
            width:200px;
            height:200px;
            border-radius: 50%;
            border:1px solid red;/*no*/
        }
    

    在px后面添加/no/,不会转化px,会原样输出。 — 一般border需用这个
    在px后面添加/px/,会根据dpr的不同,生成三套代码。—- 一般字体需用这个

    • 使用px2rem配合scss时,/px/、/no/失效:
      (1)可以把px写成大写PX,这样px2rem也不会转换,同时大写在浏览器上也是生效的。
      (2)使用普通css写,也可以生效。

    但是使用px2rem-loader修改build/utils.js文件之后会影响css样式中的背景图片的加载,为解决该问题选择卸载px2rem-loader,使用postcss-pxtorem。

    postcss-pxtorem是PostCSS的插件,用于将像素单元生成rem单位。

    • 安装
    npm install postcss-pxtorem --save-dev
    
    • 配置
      可以通过3个地方来添加配置,配置文件皆位于vue 项目根目录中,若文件不存在可以自行建立。
    • 权重
      vue.config.js > .postcssrx.js > postcss.config.js
      其中 postcssrc.js 和 postcss.config.js 可以热更新, vue.config.js 中做的修改要重启devServer。
    • 属性
      rootValue (Number)

    根元素的值,即1rem的值
    用于设计稿元素尺寸/rootValue
    比如 rootValue = 192 时,设计稿是1920*1080比例,在css中width: 960px; 最终会换算成width: 5rem;
    还有一些其他的配置:

    propList (Array) 需要做单位转化的属性.

    必须精确匹配
    用 * 来选择所有属性. Example: ['']
    在句首和句尾使用 * (['
    position'] 会匹配 background-position-y)
    使用 ! 来配置不匹配的属性. Example: ['
    ', '!letter-spacing']
    组合使用. Example: ['', '!font']
    minPixelValue(Number) 可以被替换的最小像素.
    unitPrecision(Number) rem单位的小数位数上限.

    • 配置示例
      vue.config.js
    module.exports = {
      //...其他配置
      css: {
       loaderOptions: {
        postcss: {
         plugins: [
          require('postcss-pxtorem')({
           rootValue: 192,
           minPixelValue: 2,
           propList: ['*'],
          })
         ]
        }
       }
      },
     }
    

    .postcssrc.js

    module.exports = {
      plugins: {
        'postcss-pxtorem': {
          rootValue: 16,
          minPixelValue: 2,
          propList: ['*'],
        }
      }
    }
    

    postcss.config.js

    module.exports = {
     plugins: {
      'postcss-pxtorem': {
       rootValue: 192,
       minPixelValue: 2,
       propList: ['*'],
      }
     }
    }
    

    这样配合flexible即可实现px转rem的适配。
    如果不适用flexible,则新建rem.js文件,于main.js中引用。

    // 设计稿以1920px为宽度,而我把页面宽度设计为10rem的情况下
     
    const baseSize = 192; // 这个是设计稿中1rem的大小,此处要和postcss-pxtorem配置中的rootValue一致。
    function setRem() {
      // 实际设备页面宽度和设计稿的比值
      const scale = document.documentElement.clientWidth / 1920 || document.body.clientWidth / 1920;
      // 计算实际的rem值并赋予给html的font-size
      document.documentElement.style.fontSize = (baseSize * scale) + 'px';
    }
    setRem();
    window.addEventListener('resize', () => {
      setRem();
    });
    

    相关文章

      网友评论

        本文标题:网页的自适应布局和px转rem方案

        本文链接:https://www.haomeiwen.com/subject/bexjfhtx.html