Lenny-Hu / note

blog
5 stars 1 forks source link

移动端适配之remjs vw vh #64

Open Lenny-Hu opened 5 years ago

Lenny-Hu commented 5 years ago

淘宝所用的rem方案

https://github.com/amfe/lib-flexible/tree/master

使用文档 https://github.com/amfe/article/issues/17

其它使用文章

Lenny-Hu commented 5 years ago

为什么移动端设计稿总是640px和750px?

在我开始写移动端页面至今,一直有2个疑问困扰着我,我只知道结果但不知道为什么

  问题1:为什么设计师给的设计稿总是640px或750px(现在一般以Phone6为基准,给的750px)

  问题2:为什么我们拿到640px和750px的设计稿,在编码的时候都要除以2,

     (比如设计稿上有一个图标宽高是4040,我们需要先除以2,实际编码时候宽高要写成2020)


结论:pt和px的关系就是—— 1pt 里面有几个像素点

    (比如 1pt里面有1个px,也可以有2个,3个,分别对应上图的@1x,@2x,@3x)

  下图的Reader就是反应它们之间的比例,即 pt 和 px为1:2

  还是拿iPhone6举例,下图 pt 宽高是375667,px 宽高是7501334,px的宽高是pt的2倍。

1033257-20180906100351775-1261095461

  所以这里的Reader关系是@2x,也就是2倍

  所以为什么设计稿640px和750px要除以2,就是因为设计师给的640px和750px是物理像素

  而我们在浏览器模拟调试移动端的时候看到的像素是逻辑像素


https://www.cnblogs.com/tu-0718/p/9596894.html

H5案例分享:Retina显示屏-揭秘移动端的视觉稿通常会设计为传统PC的2倍

h5页面设计稿640下20px,逻辑像素就是10px的字体

Lenny-Hu commented 5 years ago

使用vw + rem布局

mixin代码文件


/* 移动端页面设计稿宽度 */
$design-width: 640;
/* 移动端页面设计稿dpr基准值 */
$design-dpr: 2;
/* 将移动端页面分为10块 */
$blocks: 10;
/* 缩放所支持的设备最小宽度 */
$min-device-width: 320px;
/* 缩放所支持的设备最大宽度 */
$max-device-width: 640px;

// 公共
@mixin bg-image($url, $width, $height) {
  background-image: url("/" + $url + "@2x.png");
  background-size: $width $height;
  background-repeat: no-repeat;
}

/* html根元素的font-size定义,简单地将页面分为$blocks块,方便计算 */
/* 当移动端X方向宽度在320-640px之间时,html 的fontsize使用的单位才是vw */
@mixin root-font-size() {
    font-size: 100vw / $blocks;

    body {
            @include container-min-width();
    }

    /* 最小宽度定义:这时候html的fontsize 为 16px */
    @media screen and (max-width: $min-device-width) {
            font-size: $min-device-width / $blocks;
    }

    /* 最大宽度定义:这时候html的fontsize 为 64px  */
    & {
            body {
                    @include container-max-width();
            }

            @media screen and (min-width: $max-device-width) {
                    font-size: $max-device-width / $blocks;
            }
    }
}

@function strip-units($number){
  @return $number / ($number * 0 + 1);
}

/* 单位px转化为rem */
@function px2rem($px) {
  @return #{strip-units($px) / $design-width * $design-dpr * $blocks}rem;
}

/* 适用于相对于版心容器转换 */
@function px2remByBox($px, $box-width: $center-width) {
  @return #{strip-units($px) / $box-width * $design-dpr * $blocks}rem;
}

/* 百分比转换 */
@function px2per($px, $box-width: $center-width) {
  @return #{strip-units($px) / $box-width * 100%};
}

/* 设置容器拉伸的最小宽度 */
@mixin container-min-width() {
    margin-right: auto;
    margin-left: auto;
    min-width: $min-device-width;
}

/* 设置容器拉伸的最大宽度 */
@mixin container-max-width() {
    margin-right: auto;
    margin-left: auto;
    max-width: $max-device-width;
}

@for $var from 12 to 60 {
  .f-fs-#{$var} {
    font-size: px2rem($var);
    }
    .f-lh-#{$var} {
        line-height: px2rem($var);
    }
}

$colorList: '000', 'fff', 'ccc', '009754', 'FF6000', '5D4646', 'FF5050', '2DBE7F', '607FD9', 'F137E6', '272727', 'FF2C4F', '232323', '004728', '006438', 'FF392A', 'ECECEC', '1E7459', 'FF476A';
@each $var in $colorList {
  .s-fc-#{$var} {
    color: unquote('##{$var}');
  }
  .s-bgc-#{$var} {
    background-color: unquote('##{$var}');
  }
}

// 重置
* {
  box-sizing: border-box;
}

img {
  max-width: 100%;
  height: auto;
}

/* function */
.f-cb:after,.f-cbli li:after{display:block;clear:both;visibility:hidden;height:0;overflow:hidden;content:".";}
.f-cb,.f-cbli li{zoom:1;}
.f-ib{display:inline-block;*display:inline;*zoom:1;}
.f-dn{display:none;}
.f-db{display:block;}
.f-fl{float:left;}
.f-fr{float:right;}
.f-pr{position:relative;}
.f-prz{position:relative;zoom:1;}
.f-oh{overflow:hidden;}
.f-ff0{font-family:arial,\5b8b\4f53;}
.f-ff1{font-family:"Microsoft YaHei",\5fae\8f6f\96c5\9ed1,arial,\5b8b\4f53;}
.f-fs1{font-size:12px;}
.f-fs2{font-size:14px;}
.f-fwn{font-weight:normal;}
.f-fwb{font-weight:bold;}
.f-tal{text-align:left;}
.f-tac{text-align:center;}
.f-tar{text-align:right;}
.f-taj{text-align:justify;text-justify:inter-ideograph;}
.f-vam,.f-vama *{vertical-align:middle;}
.f-wsn{word-wrap:normal;white-space:nowrap;}
.f-pre{overflow:hidden;text-align:left;white-space:pre-wrap;word-wrap:break-word;word-break:break-all;}
.f-wwb{white-space:normal;word-wrap:break-word;word-break:break-all;}
.f-ti{overflow:hidden;text-indent:-30000px;}
.f-ti2{text-indent:2em;}
.f-lhn{line-height:normal;}
.f-tdu,.f-tdu:hover{text-decoration:underline;}
.f-tdn,.f-tdn:hover{text-decoration:none;}
.f-toe{overflow:hidden;word-wrap:normal;white-space:nowrap;text-overflow:ellipsis;}
.f-csp{cursor:pointer;}
.f-csd{cursor:default;}
.f-csh{cursor:help;}
.f-csm{cursor:move;}
.f-usn{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none;}

// 组件样式
.m-dialog-box,
.m-loading-box {
    display: flex;
    align-items: center;
    justify-content: center;
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 1050;
    background: rgba(0, 0, 0, 0.5);
}

.m-dialog-body {
    position: relative;

    .close {
        position: absolute;
        right: px2rem(5);
        top: - px2rem(46);
        width: px2rem(42);
        height: px2rem(42);
        @include bg-image('close', px2rem(42), px2rem(42));
        background-position: center;
        background-repeat: no-repeat;
    }
}

.m-loading-inner {
    border-radius: px2rem(8);
    padding: px2rem(14);

    .img-box {
        margin-bottom: px2rem(4); 
    }
}

.m-no-data {
    display: block;
    width: 100%;
    opacity: 0.8;
}

在一些pc到移动端的自适应中,可能整体缩小在移动端字体会很小,有2种方法可以处理:

  1. 使用媒体查询,然后用px2remByBox覆盖一遍尺寸定义,缺点是得多写一遍,例如:

    .a {
    width: px2rem(100);
    font-size: px2rem(20);
    
    $box: 700;
    
    @media screen and (max-width: 768px) {
    width: px2remByBox(100, $box);
    font-size: px2remByBox(20, $box);
    }
    }
  2. 有的地方使用em为单位,在小屏幕下使用媒体查询控制字体就行。例如:
    
    $fs: 20; // 最小的字体,移动端最小显示为12px。
    @function px2em ($px, $_fs: $fs) {
    @return #{$px / $_fs}em;
    }
    // 按比例设置最小字体,小屏幕最小设置为12px字体
    @function getminfs ($target, $base: $fs) {
    @return #{round(12 / $base * $target)}px;
    }
    @mixin mobile-screen($width: 768px)
    {
    @media screen and (max-width: $width)
    {
    @content;
    }
    }
    // 设置最小字体
    @mixin minFontSize ($size: 12px) {
    @include mobile-screen () {
    font-size: $size;
    }
    }

font-size: px2rem($fs); @include minFontSize;

.a { padding: px2em(50, 26) 0 0; font-size: px2rem(26); // 这是为了适应pc-768px之间的屏幕

@include minFontSize(getminfs(26)); // 按比例缩小的字体,20px的字在小屏幕显示为12px,那么26px的字相对于这个比例 }

Lenny-Hu commented 5 years ago

关于移动端rem与px换算的计算方式

https://blog.csdn.net/daimomo000/article/details/81610178

Lenny-Hu commented 4 years ago

腾讯新闻所用的JS计算html节点的fontsize

https://xw.qq.com

(function(base, min, max, scaling){
  var cacheWidth = 0;
  var timer;
  var docEl = document.documentElement;
  var resizeEvt = 'onorientationchange' in window ? 'orientationchange' : 'resize';
  var recalc = function () {
    var clientWidth = docEl.clientWidth;
    if (!clientWidth) return;
    clientWidth = Math.min(clientWidth, max);
    clientWidth = Math.max(clientWidth, min);
    if(cacheWidth !== clientWidth) {
      clearInterval(timer);
      cacheWidth = clientWidth;
      docEl.style.fontSize = scaling * (clientWidth / base) + 'px';
    }
  }
  if (!document.addEventListener) return;
  window.addEventListener(resizeEvt, function() {
    timer = setInterval(recalc, 10);
  });
  recalc();
})(375, 300, 768, 100);

其设计图为 750,尺寸计算公式为 1rem = 100px, 3.75rem = 375px,sass计算函数如下

// 移除单位
@function strip-units($number){
  @return $number / ($number * 0 + 1);
}

/* 单位px转化为rem */
@function px2rem($px) {
  @return #{strip-units($px) / 2 / 100}rem; // 如果设计图已经按375标注了,无需除以2
}
Lenny-Hu commented 4 years ago

利用viewport,适配各种屏幕

使用px写各种尺寸,利用js动态设置mete的viewport来达到适配的效果

(function () {
    var phoneScale = parseInt(window.screen.width) / 375;
    document.querySelector('meta[name="viewport"]').setAttribute('content', 'width=375, minimum-scale=' + phoneScale + ', maximum-scale=' + phoneScale + ', user-scalable=no');
})();

利用该方法可以使网页自动缩放,达到简单粗暴的适配效果,可能存在以下问题:

参考资源 https://www.zhihu.com/question/32198592