em:
相对长度单位,相对于父级元素的字体大小或浏览器的默认字体尺寸,
注意:
元素的
width/height/padding/margin
用
em
的话相对于该元素自身的font-size。
rem:
相对长度单位,相对于页面
根元素html
的字体大小。
rpx:
是微信小程序解决自适应屏幕尺寸的尺寸单位。微信小程序规定以
iPhone6
标准,屏幕宽度为
375px
,把它分为
750rpx
,
1rpx = 0.5px
。微信小程序同时也支持
rem
尺寸单位, 规定屏幕的宽度为
20rem
, 所以
1rem = (750/20)rpx = 37.5 rpx
。
.box {
font-size: 4em;
width: 5em;
height: 5em;
border: 2px solid gold;
.child {
font-size: 0.5em;
width: 5em;
height: 5em;
background-color: antiquewhite;
<div class="box">
我是父元素
<div class="child">我是子元素</div>
</div>
二、屏幕尺寸、分辨率、PPI(像素密度)的关系
屏幕尺寸: 显示器对角线的物理长度,1英寸=2.54厘米。
物理分辨率:,屏幕横向和纵向分布的像素点数,逻辑分辨率
以point(pt)为单位,物理分辨率
以pixel(px)为单位。如1920 x 1080
【在使用显示器时选择过低分辨率,会让原本正常显示的内容有很大的缩放比,容易出现看不全所有内容的情况,这时需要调整系统的缩放比例才能正常使用;而在使用小尺寸显示器时选择过高分辨率,会让原本正常显示的内容有很大的缩放比。容易出现缩小而看不清文字的情况】
PPI: (Pixels Per Inch),含义是显示器屏幕每英寸所拥有的像素数量,PPI是计算的显示器对角线上每英寸直线穿过的像素数【相同显示面积下的PPI越高,对机器性能的要求就越大。游戏在4K分辨率下要比2K分辨率下的帧数低很多。一般玩家会选择降低分辨率以获得流畅的游戏体验】
清晰度: PPI决定图像清晰度高低;而分辨率仅代表像素数量,但屏幕大小未考虑进去。
区分逻辑分辨率和物理分辨率,是因为在早期iPhone 3GS之前,iOS绘制图形以point为单位。在这个时期point和pixel严格对应在一起。在iPhone 3GS上:1 pt = 1 px。到了iPhone 4开始,苹果引入了Retina屏幕。在一定物理单位内可以显示2倍的像素。iPhone 4的屏幕物理尺寸还是3.5寸,分辨率为640 × 960,提升了4倍。也就是说,原先的1 point可以容纳4个pixel。
历代iPhone的分辨率
CSS像素 或 逻辑像素 或 设备独立像素: 操作系统定义的单位。如果手机分辨率翻倍,图像不就要被缩小一倍,难道要针对每个设备都出个设计稿?每个设备的分辨不尽相同,其实这个问题乔帮主
在很多年前就想到了——就是逻辑分辨率;在iPhone4使用的视网膜屏幕中,把2x2个物理像素当1个像素使用,这样让屏幕看起来更精致,但是元素的大小却不会改变。从此以后高分辨率的设备,多了一个逻辑像素。既然逻辑像素由物理像素得来,那他们就会有一个像素比值,像素比会产生一个非常经典的问题,1像素边框的问题。
设备像素 或 物理像素: 设备能够控制显示的最小单位
设备像素比: 设备像素比 = 设备像素 / 设备独立像素
,单位是dpr(device pixel radio);PPI值越高,意味着有更细腻的画面;而在一定的距离内,手机显示屏在200PPI以上时,肉眼就分辨不出单个像素点了,所以没必要过度追求超高的PPI。
1px边框问题 (物理像素 => 逻辑像素)进行显示
当css里写的1px的时候,由于它是逻辑像素,导致逻辑像素根据这个设备像素比(dpr)去映射到设备上就为2px,或者3px,由于每个设备的屏幕尺寸不一样,就导致每个物理像素渲染出来的大小也不同(记得上面的知识点吗,设备的像素大小是不固定的),这样如果在尺寸比较大的设备上,1px渲染出来的样子相当的粗矿,这就是经典的一像素边框问题
transform: scale(0.5) 方案
@media only screen and (-webkit-min-device-pixel-ratio: 2.0) {
.border-bottom::after {
display: block;
content: '';
height: 1px;
background:#000;
transform: scaleY(0.5);
四. 屏幕适配解决方案
视口(viewport)
代表当前可见的计算机图形区域。在Web浏览器术语中,通常与浏览器窗口相同,但不包括浏览器的UI, 菜单栏等——即指你正在浏览的文档的那一部分。其中user-scalable
设置为 no
可以解决移动端点击事件延迟问题(拓展)
<meta name="viewport" content="width=device-width; initial-scale=1; maximum-scale=1; minimum-scale=1; user-scalable=no;">
UI
给我们的原型图一般是基于iphone6
设备机型的像素给定的;为了适配所有机型,我们在写样式时需要把物理像素转换为设备独立像素
方法一:基于 rem 的 flexible方案(已经被官方弃用)
由于viewport单位得到众多浏览器的兼容,lib-flexible这个过渡方案已经可以放弃使用,不管是现在的版本还是以前的版本,都存有一定的问题。建议大家开始使用viewport来替代此方案。(来自lib-flexible团队)
它的核心代码非常简单:
function setRemUnit () {
const rem = document.documentElement.clientWidth.clientWidth / 10
docEl.style.fontSize = rem + 'px'
window.addEventListener('resize', setRemUnit)
window.addEventListener('pageshow', function (e) {
if (e.persisted) {
setRemUnit()
上面的代码中,将html
节点的font-size
设置为页面clientWidth
(布局视口)的1/10
,即1rem
就等于页面布局视口的1/10
,这就意味着我们后面使用的rem
都是按照页面比例来计算的。
以iPhone6
为例:布局视口为375px
,则1rem = 37.5px
,这时UI
给定一个元素的宽为75px
(设备独立像素),我们只需要将它设置为75 / 37.5 = 2rem
。
当然,每个布局都要计算非常繁琐,我们可以借助PostCSS
的px2rem
插件来帮助我们完成这个过程。
被弃用原因: 没有考虑到设备像素比,用户使用更大的屏幕,是想看到更多的内容,而不是更大的字;仅仅只是随屏幕大小同步放大或缩小页面内容
方法二:vh、vw方案
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
中的较大值
如果视觉视口为375px
,那么1vw = 3.75px
,这时UI
给定一个元素的宽为75px
(设备独立像素),我们只需要将它设置为75 / 3.75 = 20vw
。
这里的比例关系我们也不用自己换算,我们可以使用PostCSS
的 postcss-px-to-viewport
插件帮我们完成这个过程。写代码时,我们只需要根据UI
给的设计图写px
单位即可。
vw
同样有一定的缺陷:
px
转换成vw
不一定能完全整除,因此有一定的像素差。
比如当容器使用vw
,margin
采用px
时,很容易造成整体宽度超过100vw
,从而影响布局效果。当然我们也是可以避免的,例如使用padding
代替margin
,结合calc()
函数使用等等...
方法三:viewport
+ window.devicePixelRatio
+ rem
实现原理: 首先通过JS
动态获取window.devicePixelRatio
,然后动态修改具有viewport
属性的meta
标签元素的content
属性 (个人觉得最好、个人最推荐的方法)
blog.csdn.net/qq131125669…
www.meow7.cn/index.php/a…
方法四:Flex布局
方法五:媒体查询
@media only screen
and (min-width: 320px)
and (max-width: 480px)
and (resolution: 150dpi) {
body { line-height: 1.4; }
@media (-webkit-device-pixel-ratio: 1) {
p { color: red; }
@media (-webkit-min-device-pixel-ratio: 1.1) {
p { font-size: 1.5em;}
@media (-webkit-max-device-pixel-ratio: 3) {
p { background: yellow;}
@media (height > 600px) {
body { line-height: 1.4; }
@media (400px <= width <= 700px) {
body { line-height: 1.4; }
七、适配iPhoneX
iPhoneX
的出现将手机的颜值带上了一个新的高度,它取消了物理按键,改成了底部的小黑条,但是这样的改动给开发者适配移动端又增加了难度。
7.1 安全区域
在iPhoneX
发布后,许多厂商相继推出了具有边缘屏幕的手机。
这些手机和普通手机在外观上无外乎做了三个改动:圆角(corners
)、刘海(sensor housing
)和小黑条(Home Indicator
)。为了适配这些手机,安全区域这个概念变诞生了:安全区域就是一个不受上面三个效果的可视窗口范围。
为了保证页面的显示效果,我们必须把页面限制在安全范围内,但是不影响整体效果。
7.2 viewport-fit
viewport-fit
是专门为了适配iPhoneX
而诞生的一个属性,它用于限制网页如何在安全区域内进行展示。
contain
: 可视窗口完全包含网页内容
cover
:网页内容完全覆盖可视窗口
默认情况下或者设置为auto
和contain
效果相同。
7.3 env、constant
我们需要将顶部和底部合理的摆放在安全区域内,iOS11
新增了两个CSS
函数env、constant
,用于设定安全区域与边界的距离。
函数内部可以是四个常量:
safe-area-inset-left
:安全区域距离左边边界距离
safe-area-inset-right
:安全区域距离右边边界距离
safe-area-inset-top
:安全区域距离顶部边界距离
safe-area-inset-bottom
:安全区域距离底部边界距离
注意:我们必须指定viweport-fit
后才能使用这两个函数:
<meta name="viewport" content="viewport-fit=cover">
constant
在iOS < 11.2
的版本中生效,env
在iOS >= 11.2
的版本中生效,这意味着我们往往要同时设置他们,将页面限制在安全区域内:
body {
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
当使用底部固定导航栏时,我们要为他们设置padding
值:
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
八、横屏适配
很多视口我们要对横屏和竖屏显示不同的布局,所以我们需要检测在不同的场景下给定不同的样式:
8.1 JavaScript检测横屏
window.orientation
:获取屏幕旋转方向
window.addEventListener("resize", ()=>{
if (window.orientation === 180 || window.orientation === 0) {
console.log('竖屏');
if (window.orientation === 90 || window.orientation === -90 ){
console.log('横屏');
8.2 CSS检测横屏
@media screen and (orientation: portrait) {
@media screen and (orientation: landscape) {
九、图片模糊问题
9.1 产生原因
我们平时使用的图片大多数都属于位图(png、jpg...
),位图由一个个像素点构成的,每个像素都具有特定的位置和颜色值:
理论上,位图的每个像素对应在屏幕上使用一个物理像素来渲染,才能达到最佳的显示效果。
而在dpr > 1
的屏幕上,位图的一个像素可能由多个物理像素来渲染,然而这些物理像素点并不能被准确的分配上对应位图像素的颜色,只能取近似值,所以相同的图片在dpr > 1
的屏幕上就会模糊:
9.2 解决方案
为了保证图片质量,我们应该尽可能让一个屏幕像素来渲染一个图片像素,所以,针对不同DPR
的屏幕,我们需要展示不同分辨率的图片。
如:在dpr=2
的屏幕上展示两倍图(@2x)
,在dpr=3
的屏幕上展示三倍图(@3x)
。
9.3 media查询
使用media
查询判断不同的设备像素比来显示不同精度的图片:
.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);
只适用于背景图\
9.4 image-set
使用image-set
:
.avatar {
background-image: -webkit-image-set( "conardLi_1x.png" 1x, "conardLi_2x.png" 2x );
只适用于背景图\
9.5 srcset
使用img
标签的srcset
属性,浏览器会自动根据像素密度匹配最佳显示图片:
<img src="conardLi_1x.png"
srcset=" conardLi_2x.png 2x, conardLi_3x.png 3x">
9.6 JavaScript拼接图片url
使用window.devicePixelRatio
获取设备像素比,遍历所有图片,替换图片地址:
const dpr = window.devicePixelRatio;
const images = document.querySelectorAll('img');
images.forEach((img)=>{
img.src.replace(".", `@${dpr}x.`);
9.7 使用svg
SVG
的全称是可缩放矢量图(Scalable Vector Graphics
)。不同于位图的基于像素,SVG
则是属于对图像的形状描述,所以它本质上是文本文件,体积较小,且不管放大多少倍都不会失真。
除了我们手动在代码中绘制svg
,我们还可以像使用位图一样使用svg
图片:
<img src="conardLi.svg">
<img src="data:image/svg+xml;base64,[data]">
.avatar {
background: url(conardLi.svg);
99designs.com/blog/tips/p…
www.w3cplus.com/css/vw-for-…
aotu.io/notes/2017/…
用户5478764823586
粉丝