响应式布局

1、响应式布局和自适应布局区别

1.1 自适应布局

根据浏览器窗口的缩放等比例缩放页面内容(看到的页面布局不变,是原页面的缩小版)

1.2 响应式布局

根据浏览器窗口的变化,不同的宽度,展示不同的布局(页面布局发生了变化)

2、常见网页缩放方案

  • 百分比布局%
  • Media 媒体查询
  • rem 布局
  • Viewport(vw/vh)

3、百分比布局

这是最早的缩放布局解决方案,解决成本低,高效,但因为一些缺陷,已经被淘汰,目前主要用于局部使用
百分比布局又称为流式布局,单位是%
使用重点是参考谁的百分比:父元素(不计算padding),body等等,padding百分比参考父元素width

将页面元素的宽度以百分比来进行设置,高度不变。缺点也显而易见,在例如

  • ipad横屏下,页面被拉伸很多,造成视觉体验较差。
  • 百分比必须要参考父元素等其他部分

4、Media 媒体查询

为了解决百分比布局带来的宽屏视觉上的缺点,引入了media的方案,将设备按分辨率分成几个标准化的区间,视觉根据区间设计出2-3个方案(方案数量决定了精细化的程度),前端根据media来区分在某个分辨率区间读取相应的css方案。

⚠️⚠️⚠️ 注意:缺点是需要设计和前端同时多出多个方案,较为麻烦。

使用方式:@media 媒体类型and (媒体特性){你的样式}

@media screen and (max-width:480px){
 .ads {
   display:none;
  }
}
//一起写
html{font-size:10px}
@media screen and (min-width:320px) and (max-width:480px){html{font-size:12px}}
@media screen and (min-width:480px) and (max-width:640px){html{font-size:14px}}
@media screen and (min-width:640px){html{font-size:16px}}

css也可

div{
  min-width:500px;
  max-width:800px;
  min-height:1200px
}

5、手淘flexible + rem布局

  • 是目前比较主流的解决方案:Flexible-下载地址

Flexible作为比较知名的成熟方案,也已经出现很久了,技术原理主要就是为了能让页面更好的适配各种不同的终端,通过Hack手段来根据设备的dpr值相应改变标签中viewport的值,从而让页面达么缩放的效果,也变相的实现页面的适配功能。

  • em是单位,表示是父元素的多少倍
  • rem:r是root的缩写,根元素的倍数(可使用cssrem插件)

缺点:

  • 必须头部导入一个flexible.js
  • 缩放依赖于html的font-size
<!-- dpr = 1--> <meta name="viewport" content="initial-scale=scale,maximum-scale=scale,minimum-scale=scale,user-scalable=no">
<!-- dpr = 2--> <meta name="viewport" content="initial-scale=0.5,maximum-scale=0.5,minimum-scale=0.5,user-scalable=no"> 
<!-- dpr = 3--> <meta name="viewport" content="initial-scale=0.3333333333,maximum-scale=0.3333333333,minimum-scale=0.3333333333,user-scalable=no">

Flexible 事实上做了这几样事情:

  1. 动态改写<meta>标签
  2. <html>元素添加 data-dpr 属性,并且动态改写 data-dpr 的值
  3. <html>元素添加 font-size 属性,并且动态改写 font-size 的值
  4. 把视觉稿中的 px 转换成 rem
  5. 文字字号使用 px,不使用 rem

Flexible技术原理,其思想被总结出来有三点

  • 根据dpr的值来修改viewport实现1px的线
  • 根据dpr的值来修改html的font-size,从而使用rem实现等比缩
  • 使用Hack手段用rem模拟vw特性

flexible.js 源码:

(function flexible(window, document) {
    
    var docEl = document.documentElement;   //获取dom
    var dpr = window.devicePixelRatio || 1;   //获取dpr,默认为1
  
    // adjust body font size
    function setBodyFontSize() {
      if (document.body) {
        document.body.style.fontSize = 12 * dpr + "px";  //正文字体,不设置默认字体过大
      } else {
        document.addEventListener("DOMContentLoaded", setBodyFontSize);
      }
    }
    setBodyFontSize();
  
    // set 1rem = viewWidth / 10
    function setRemUnit() {
      var rem = docEl.clientWidth / 24;  //  设计稿宽度分为24份
      docEl.style.fontSize = rem + "px";
    }
  
    setRemUnit();
  
    // reset rem unit on page resize
    window.addEventListener("resize", setRemUnit);
    window.addEventListener("pageshow", function(e) {
      if (e.persisted) {
        setRemUnit();
      }
    });
  
    // detect 0.5px supports
    if (dpr >= 2) {
      var fakeBody = document.createElement("body");
      var testElement = document.createElement("div");
      testElement.style.border = ".5px solid transparent";
      fakeBody.appendChild(testElement);
      docEl.appendChild(fakeBody);
      if (testElement.offsetHeight === 1) {
        docEl.classList.add("hairlines");
      }
      docEl.removeChild(fakeBody);
    }
  })(window, document);
  

6、VW/VH 布局

vw布局因为兼容问题被解决,目前逐渐成为主流方案,Flexible的GitHub上也推荐使用vw布局,作者表示vw布局方案已得到了浏览器的支持,不需要hack了

视口的介绍:

因为当时大多数网页以980px为版心,乔布斯提出了,调整手机像素比,将手机设置为980px,这样来实现对网页的一个兼容显示,此时手机刚刚可以卡住版心区域,以此来解决网页在手机端显示过小的问题。

之后,乔布斯再次改进,提出开发者可根据需求自定义视口宽度,即 viewport

物理像素:最大分辨率

设备独立像素:默认分辨率,操作系统设置

设备像素比:物理像素/设备独立像素

设备像素比:

我们可以通过设备像素比 dpr(device pixel ratio)来获取或者设置当前设备的像素比

根据window.devicePixelRatio来获取当前的设备像素比

显示浏览器宽高

//获取浏览器宽高
var h = document.getElementByTagName('h1')[0]
h.innerHTML = document.documentElement.clientWidth 

//获取当前的设备像素比
var h2 = document.getElementByTagName('h1')[1]
h.innerHTML = window.devicePixelRatio    

我们可以设置下面代码,为设备宽度,此时会计算出当前设备的视口宽度,比如iPhone默认375px

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
content:"width=980px" //视口宽度设置为980px

viewport: 一般指的是浏览器窗口内容区的大小,不包含工具条、选项卡等内容

content常用属性值:

content:自定义视口宽度,默认

  • width: 浏览器宽度,输出设备中的页面可见区域宽度

    • width=device-width 约束视口的宽度
  • initial-scale=1.0 : 初始视口的宽度缩放比例为一倍

  • maximum-scale=1.0 : 最大缩放比例(1.0-10.0)

  • minimum-scale=1.0 : 最小缩放比例(1.0-10.0)

  • User-scalable = no是否允许用户缩放,默认Yes

Viewport相关的单位有四个,分别为vw、vh、vmin和vmax。

vw:是Viewport's width的简写,1vw等于window.innerWidth的1%。

vh:和vw类似,是Viewport's height的简写,1vh等于window.innerHeihgt的1%。

vmin:vmin的值是当前vw和vh中较小的值。

vmax:vmax的值是当前vw和vh中较大的值。
vw单位实现弹性布局
我们先来看看这vw vh单位 w3c的官方解释
vw:1% of viewport’s width
vh:1% of viewport’s height

viewport即浏览器可视区域大小
我们可以这样理解 100vw = window.innerwidth, 100vh = window.innerheight
在移动端我们一般都可以认为,100vw就是屏幕宽度。若使用vw布局,就不需要再像rem那样,在js中去动态设置根元素的font-size了,sass中只需要使用这个函数做转换即可

//以iphone7尺寸@2x 750像素宽的视觉稿为例
@function vw($px) {
    @return ($px / 750) * 100vw;
}

//假设一个div元素在视觉稿中,宽度为120px,字体大小为12px
div {
    width: vw(120);
    font-size: vw(12);
} 

在这个方案中,我们用vw来代替rem的缩放方案,就可以将页面做到任意环境下的同等自适应缩放。
2、安装postcss
要实现使用vw来实现移动端的适配,我们先需要安装postcss。一般来说是这样:

$ npm i postcss-loader --save-dev

对于postcss我以前在webpack从0到1-less、sass、postcss
就提到过,可以将它理解为是一个平台化的概念,有很多插件被大家开发出来为它赋能,实现vw适配就是要利用这么一个插件:postcss-px-to-viewport,先安装它:

$ npm install postcss-px-to-viewport --save-dev

它可以将我们设置px值自动转化为相应的vw、vh之类的值。

6、横纵向等比缩放示例

body{
  overflow: hidden;
}
#container{
  margin: 0;
  padding: 0;
  width: 1920px;
  height: 937px;
  box-sizing: border-box;
  overflow: hidden;
}

export class AppComponent implements OnInit, AfterViewInit {
  title = 'ECUI';
  constructor() {
    window.addEventListener('resize', () => {
      this.resize()
    })
  }
  ngAfterViewInit(): void {
    this.resize()
  }
  ngOnInit(): void {}

  resize() {
    var rate_width = parseFloat("" + document.body.clientWidth / 1920);
    var rate_height = parseFloat("" + document.body.clientHeight / 937);
    //console.log("宽",document.body.clientWidth,"高",document.body.clientHeight);
    var contain = document.getElementById("container")
    contain.style.transformOrigin = "left top"
    contain.style.transform = "scaleX(" + rate_width + ") scaleY(" + rate_height + ")"
  }
}

附录:
meta标签常用属性:
https://blog.csdn.net/weixin_42133469/article/details/81588097
大屏项目案例:
https://gitee.com/daoke0818/pro_bigScreenCharts#大屏图表前端开发案例
伪元素讲解:
https://www.jianshu.com/p/37f639f108dd

posted @ 2020-08-25 23:45  Daeeman  阅读(198)  评论(0编辑  收藏  举报