响应式布局
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 事实上做了这几样事情:
- 动态改写
<meta>
标签 - 给
<html>
元素添加data-dpr
属性,并且动态改写data-dpr
的值 - 给
<html>
元素添加font-size
属性,并且动态改写font-size
的值 - 把视觉稿中的
px
转换成rem
- 文字字号使用
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