英寸:描述屏幕的物理大小 屏幕n寸:屏幕对角线的长度
1英寸 = 2.54 厘米
物理像素:图片或电子屏幕的最小组成单位
分辨率:一个屏幕具体由多少个物理像素点组成
- 屏幕分辨率
- 图像分辨率 例如:iPhone SE分辨率:1136 x 640,表示在垂直和水平上所具有的物理像素点。
PPI(Pixel Per Inch):每英寸包括的物理像素点。用于描述屏幕的清晰度以及一张图片的质量
例如iphone 6的PPI(对角线每一英寸包含的物理像素点):(水平物理像素点的平方 + 垂直物理像素点的平方)开根号 / 对象线英寸
DPI(Dot Per Inch):即每英寸包括的点数 这里的点是一个抽象的单位,它可以是屏幕像素点、图片像素点也可以是打印机的墨点
设备独立像素(Device Independent Pixels)简称DIP或DP:逻辑像素(css像素),告诉不同分辨率的手机,它们在界面上显示元素的大小是多少
例子:在iPhone4使用的视网膜屏幕中,把2x2个像素当1个像素使用,这样让屏幕看起来更精致,但是元素的大小却不会改变
物理像素 in 设备独立像素 in (图片 or 屏幕)
var PX = {
0: '物理像素',
1: '物理像素'
}
var image = {
0: PX,
1: PX,
}
设备像素比dpr(device pixel ratio):物理像素 / 设备独立像素
- 在web中,浏览器为我们提供了window.devicePixelRatio来获取dpr
- 在css中,可以使用媒体查询min-device-pixel-ratio,区分dpr
设备独立像素 = pt = dp
- iOS的尺寸单位为pt
- Android的尺寸单位为dp
设备独立像素 = css像素(当页面缩放比例为100%时) 页面的缩放系数 = css像素 / 设备独立像素
Retina屏幕只是苹果提出的一个营销术语,让多个物理像素渲染一个独立像素只是Retina屏幕为了达到效果而使用的一种技术。而不是所有DPR > 1的屏幕就是Retina屏幕。
P
:屏幕纵向的像素个数。1080P即纵向有1080个像素,分辨率为1920X1080的屏幕就属于1080P屏幕
K
:屏幕横向有几个1024个像素。一般来讲横向像素超过2048就属于2K屏,横向像素超过4096就属于4K屏。
视口(viewport):在Web浏览器术语中,通常与浏览器窗口相同,但不包括浏览器的UI, 菜单栏等——即指你正在浏览的文档的那一部分。
- 布局视口
- 视觉视口
- 理想视口
布局视口(layout viewport):布局视口是网页布局的基准窗口(document.documentElement.clientWidth / clientHeight)
视觉视口(visual viewport):用户通过屏幕真实看到的区域(window.innerWidth / innerHeight)
理想视口(ideal viewport):网站页面在移动端展示的理想大小(screen.width / height)
当页面缩放比例为100%时:
- CSS像素 = 设备独立像素
- 理想视口 = 视觉视口
可以借助元素的viewport来帮助我们设置视口、缩放等,从而让移动端得到更好的展示效果
- width:以pixels(像素)为单位, 定义布局视口的宽度
- height:以pixels(像素)为单位, 定义布局视口的高度。
- initial-scale:定义页面初始缩放比率。
- minimum-scale:定义缩放的最小值;必须小于或等于maximum-scale的值。
- maximum-scale:定义缩放的最大值;必须大于或等于minimum-scale的值。
- user-scalable:如果设置为 no,用户将不能放大或缩小网页。默认值为 yes。
<meta name="viewport" content="width=device-width; initial-scale=1; maximum-scale=1; minimum-scale=1; user-scalable=no;">
为了在移动端让页面获得更好的显示效果,我们必须让布局视口、视觉视口都尽可能等于理想视口。
- width=device-width:让布局视口等于理想视口
- initial-scale=1:让视觉视口等于理想视口(initial-scale = 理想视口宽度 / 视觉视口宽度)
这时,1个CSS像素就等于1个设备独立像素
布局视口宽度取的是width和视觉视口宽度的最大值。
例如: 若手机的理想视口宽度为400px,设置width=device-width,initial-scale=2,此时视觉视口宽度 = 理想视口宽度 / initial-scale = 200px,布局视口取两者最大值即device-width 400px。 若设置width=device-width,initial-scale=0.5,此时视觉视口宽度 = 理想视口宽度 / initial-scale即800px,布局视口取两者最大值即800px。
- window.innerHeight:获取浏览器视觉视口高度(包括垂直滚动条)。
- window.outerHeight:获取浏览器窗口外部的高度。表示整个浏览器窗口的高度,包括侧边栏、窗口镶边和调正窗口大小的边框。
- window.screen.Height:获取获屏幕取理想视口高度,这个数值是固定的,设备的分辨率/设备像素比
- window.screen.availHeight:浏览器窗口可用的高度。
- document.documentElement.clientHeight:获取浏览器布局视口高度,包括内边距,但不包括垂直滚动条、边框和外边距。
- document.documentElement.offsetHeight:包括内边距、滚动条、边框和外边距。
- document.documentElement.scrollHeight:在不使用滚动条的情况下适合视口中的所有内容所需的最小宽度。测量方式与clientHeight相同:它包含元素的内边距,但不包括边框,外边距或垂直滚动条。
- border-image
- background-image
- 伪类 + transform
- svg
- 设置viewport:通过设置缩放,让CSS像素等于真正的物理像素(flexible方案)
采用rem来计算:rem 是相对于html节点的font-size来做计算的。 例如以iPhone6为例:布局视口为375px,假设1rem = (375 / 10)px = 37.5px。元素宽度75px,那么设置元素为75 / 37.5 = 2rem。 当布局视口为414px时(iPhone6 plus),1rem = (414 / 10) = 41.4px,那么元素在此时为2rem * 41.4 = 82.8px,达到适配效果。
// set 1rem = viewWidth / 10
function setRemUnit () {
var rem = docEl.clientWidth / 10
docEl.style.fontSize = rem + 'px'
}
setRemUnit();
vh、vw方案即将视觉视口宽度 window.innerWidth和视觉视口高度 window.innerHeight 等分为 100 份。
- vw(Viewport's width):1vw等于视觉视口的1%
- vh(Viewport's height) :1vh 为视觉视口高度的1%
- vmin : vw 和 vh 中的较小值
- vmax : 选取 vw 和 vh 中的较大值
例如以iPhone6为例:布局视口为375px,假设1vw = 3.75px。元素宽度75px,那么设置元素为75 / 3.75 = 20vw。 当布局视口为414px时(iPhone6 plus),1rem = 4.14px,那么元素在此时为20vw * 4.14 = 82.8px,达到适配效果。
vw同样有一定的缺陷:
- px转换成vw不一定能完全整除,因此有一定的像素差。
- 比如当容器使用vw,margin采用px时,很容易造成整体宽度超过100vw,从而影响布局效果。当然我们也是可以避免的,例如使用padding代替margin,结合calc()函数使用等等...
安全区域就是一个不受圆角(corners)、刘海(sensor housing)和小黑条(Home Indicator)的可视窗口范围
- contain: 可视窗口完全包含网页内容(左图)
- cover:网页内容完全覆盖可视窗口(右图)
- auto:默认,跟 contain 表现一致
<meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
我们需要将顶部和底部合理的摆放在安全区域内,iOS11新增了两个CSS函数env(ios >= 11.2)、constant(ios <= 11.2),用于设定安全区域与边界的距离
- safe-area-inset-left:安全区域距离左边边界距离
- safe-area-inset-right:安全区域距离右边边界距离
- safe-area-inset-top:安全区域距离顶部边界距离
- safe-area-inset-bottom:安全区域距离底部边界距离
<meta name="viewport" content="viewport-fit=cover">
<style>
body {
padding-top: constant(safe-area-inset-top); //为导航栏+状态栏的高度 88px
padding-left: constant(safe-area-inset-left); //如果未竖屏时为0
padding-right: constant(safe-area-inset-right); //如果未竖屏时为0
padding-bottom: constant(safe-area-inset-bottom);//为底下圆弧的高度 34px
}
</style>
- JavaScript检测横屏:window.orientation
window.addEventListener("resize", ()=>{
if (window.orientation === 180 || window.orientation === 0) {
// 正常方向或屏幕旋转180度
console.log('竖屏');
};
if (window.orientation === 90 || window.orientation === -90 ){
// 屏幕顺时钟旋转90度或屏幕逆时针旋转90度
console.log('横屏');
}
});
- CSS检测横屏
@media screen and (orientation: portrait) {
/*竖屏...*/
}
@media screen and (orientation: landscape) {
/*横屏...*/
}
在dpr > 1的屏幕上,位图的一个像素可能由多个物理像素来渲染,然而这些物理像素点并不能被准确的分配上对应位图像素的颜色,只能取近似值,所以相同的图片在dpr > 1的屏幕上就会模糊
一个屏幕像素来渲染一个图片像素
只适用于背景图
.avatar{
background-image: url(conardLi_1x.png);
}
@media only screen and (-webkit-min-device-pixel-ratio:2){
.avatar{
background-image: url(conardLi_2x.png);
}
}
@media only screen and (-webkit-min-device-pixel-ratio:3){
.avatar{
background-image: url(conardLi_3x.png);
}
}
只适用于背景图
.avatar {
background-image: -webkit-image-set( "conardLi_1x.png" 1x, "conardLi_2x.png" 2x );
}
<img src="conardLi_1x.png" srcset="conardLi_2x.png 2x, conardLi_3x.png 3x">
const dpr = window.devicePixelRatio;
const images = document.querySelectorAll('img');
images.forEach((img)=>{
img.src.replace(".", `@${dpr}x.`);
})
<img src="conardLi.svg">
<img src="data:image/svg+xml;base64,[data]">
<style>
.avatar {
background: url(conardLi.svg);
}
</style>