前端兼容性问题 - 屏幕尺寸兼容
点击关注公众号回复”小册” 优惠券免费领!!写在前面前端开发最让人头疼的莫过于兼容性问题,继上一篇 前端兼容性问题 - CSS、JS 兼容(https://juejin.cn/post/7309750780252471315) 之后,这一篇主要研究并解决「屏幕尺寸」的兼容性问题
目录:
当前现状解决方案模拟设备测试方案总结当前现状Android 设备情况根据OpenSignal 在 2015 年 8 月发布的基础统计数据可以知道Andoroid的设备复杂度:ANDROID FRAGMENTATION VISUALIZED
iOS 设备情况苹果公司目前已推出42款iPhone型号:维基百科
常见屏幕分辨率下面列出桌面端、移动端、平板电脑端的一些常见的屏幕分辨率,更多屏幕分辨率查阅:屏幕尺寸大全
桌面端常见屏幕分辨率(显示器)1280x720:「720p」,高清分辨率1280x1024:常见于 「4:3」 屏幕比例的显示器1366x768:现在非常常见的低分辨率显示器1600x900:较高的分辨率,常见于中等尺寸显示器「1920x1080:1080p,全高清分辨率,现在非常常见,适用于大多数显示器」2560x1440:「2K」 分辨率,适用于较大尺寸或高质量显示器3840x2160:「4K」 分辨率,适用于高端大尺寸显示器移动端常见屏幕分辨率(智能手机)iPhone 6、iPhone 6s、iPhone 7、iPhone 8 和 iPhone SE(第二代)的分辨率828x1792:iPhone XR 和 iPhone 11 的分辨率「1080x1920:许多 Android 设备的分辨率」「1125x2436:iPhone X、iPhone XS 和 iPhone 11 Pro 的分辨率」「1170x2532:iPhone 12 和 iPhone 12 Pro 的分辨率」「1440x2560:许多高端 Android 设备的分辨率」平板电脑端常见屏幕分辨率1536x2048:iPad 的 Retina 分辨率,如 iPad 3、iPad 4、iPad Air 和 iPad mini(2 代及以后)1668x2224:iPad Air(第三代)和 iPad Pro 10.5 英寸2048x2732:iPad Pro 12.9 英寸「800x1280:许多 Android 平板电脑的分辨率」「1200x1920:许多高端 Android 平板电脑的分辨率」屏幕纵横比统计以上的屏幕分辨率得出多端各自的主流纵横比
桌面端移动端平板电脑端主流纵横比16 : 9
16 : 10
21 : 9
19 : 9
19.5 : 9
16 : 9
4 : 3
16 : 9
解决方案设置 meta 标签先了解:viewportviewport 表示浏览器中用来显示网页的「可视区域」。viewport 包括以下三种:
「layout viewport」layout viewport 为网页布局的区域,它是 「html 元素的父容器」,只要不在 css 中修改 元素的宽度, 元素的宽度就会撑满 layout viewport 的宽度。
很多时候浏览器窗口没有办法显示出 layout viewport 的「全貌」,但是它确实是已经被加载出来了,这个时候滚动条就出现了,你需要「通过滚动条来浏览 layout viewport 其他的部分」。
layout viewport 用 css 像素来衡量尺寸,在缩放、调整浏览器窗口的时候不会改变。缩放、调整浏览器窗口改变的只是 visual viewport。
在桌面浏览器中,缩放100% 的时候,Layout Viewport 宽度等于内容窗口的宽度。(你几乎不会在电脑上见过横向滚动条,除非你调整缩放)
但是在移动端,缩放为 100% 的时候,Layout Viewport 不一定等于内容窗口的大小。当你用手机浏览浏览宽大的网页(这些网页没有采用响应式设计)的时候,你只能一次浏览网页的一个部分,然后通过手指滑动浏览其他部分。这就说明整个网页已经加载出来了,只不过你要一部分一部分地看。
「visual viewport」visual viewport 为视觉视口,「就是显示在屏幕上的网页区域」,它往往「只显示 layout viewport 的一部分」visual viewport 就像一台摄像机,layout viewport 就像一张纸,摄像机对准纸的哪个部分,你就能看见哪个部分。你可以改变摄像机的拍摄区域大小(调整浏览器窗口大小),也可以调整摄像机的距离(调整缩放比例),这些方法都可以改变 visual viewport,但 layout viewport 始终不变
「ideal viewport」ideal viewport 为理想视口,不同的设备有自己不同的 ideal viewport,「ideal viewport 的宽度等于移动设备的屏幕宽度」,所以其是最适合移动设备的 viewport。只要在 css 中把某一元素的宽度设为 ideal viewport 的宽度(单位用 px ),那么这个元素的宽度就是设备屏幕的宽度了,也就是宽度为100% 的效果。ideal viewport 的意义在于,无论在何种分辨率的屏幕下,那些针对ideal viewport 而设计的网站,不需要用户手动缩放,也不需要出现横向滚动条,都可以完美的呈现给用户。
利用 meta 标签控制 viewport移动设备「默认的是 layout viewport」,也就是那个比屏幕要宽的 viewport,但在进行移动端 H5 的开发时,「我们需要的是 ideal viewport」。那么怎么才能得到 ideal viewport 呢?
我们在开发 h5 页面时,最经常见的标签如下所示
metaname="viewport"content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0"
该 meta 标签的作用是让「当前 viewport 的宽度等于设备的宽度,同时不允许用户手动缩放」。如果你不这样的设定的话,那就会使用那个比屏幕宽的默认 viewport(layout viewport),也就是说会出现横向滚动条。
相关的属性意义如下所示:
width设置 layout viewport 的宽度,为一个正整数,或字符串 "width-device"height设置页面的初始缩放值,为一个数字,可以带小数initial-scale允许用户的最小缩放值,为一个数字,可以带小数minimum-scale允许用户的最大缩放值,为一个数字,可以带小数maximum-scale设置 layout viewport 的高度,这个属性对我们并不重要,很少使用user-scalable是否允许用户进行缩放,值为"no"或"yes", no 代表不允许,yes 代表允许对比页面在桌面端的预览效果
在移动端的预览效果【左图没有设置 viewport,右图设置了 viewport】
媒体查询 @media媒体查询是 CSS3 中的一项特性,允许我们根据设备的特定条件(「如窗口或视口的宽度、高度、设备的方向、分辨率等」)来应用不同的样式。这使得我们的网页在各种设备(桌面电脑、平板、手机等)和窗口大小上都有良好的显示和交互体验,也就是响应式设计的关键。
一个基本的媒体查询语法如下:
@mediamedia_typeand(media_feature){
/*匹配时的CSS样式*/
}
其中:
「media_type」是目标媒体设备的类型,如screen,print等。如果你不指定媒体类型,那意味着应用到所有媒体类型上(也就是all)。「media_feature」是特定的设备特性,如width,height等。「and」用于将多个媒体特性合并在一起,所有条件必须匹配,样式才会被应用。媒体查询的具体使用可以查阅我之前写的文章:CSS系列 -- 媒体查询(https://juejin.cn/post/6951706603842174989),在此不作赘述
自适应单位自适应单位包括 rem,vw 和百分比%等
rem 单位rem 是根据 「根元素(html)字体大小」 变化的相对单位。rem 的全名是 「root em」,其值是相对于根元素的字体大小计算的。这意味着调整根元素的字体大小后,所有使用 rem 单位的元素都会自动调整。介绍如下:
rem 是基于根元素(即 html 元素)字体大小计算的计算公式:1 rem = 根元素字体大小示例:
!DOCTYPEhtml
html
head
style
html{
font-size:16px;
}
p{
font-size:1.25rem;
}
/style
/head
body
pHello,World!/p
/body
/html
在这个例子中,通过设置根元素字体大小为 16px,并为 元素设置颜色值为 1.25rem,计算出 的字体大小为 (16 * 1.25)px = 20px。
vw、vh 单位vw 是基于「视口宽度」的相对单位,vh 则是基于「视口高度」的相对单位。
?视口的定义:web 页面能渲染的地方
?其中 vw 是 「viewport width」 的缩写。vw 单位是基于浏览器窗口宽度的相对度量,可以让元素自适应调整,无论设备大小。介绍如下:
vw 是基于视口的宽度计算的计算公式:1 vw = 视口宽度的1%示例:
div{
width:50vw;
}
在这个例子中,将 div 的宽度设置为视口宽度的一半,即 50vw。如果视口宽度为 1200px,div 的宽度为 (1200 * 50/100)px = 600px。
rem 和 vw 的区别?"rem" 更适合用于字体大小、间距、边框等相对比较小的元素,因为这些元素「大小的变化相对不会太大」"vw" 更适合用于相对于视口宽度而言较大的元素,例如页面的宽度或高度、容器的宽度等?百分比 % 单位百分比单位%是相对于其「父元素」的尺寸来定义的。这意味着元素会根据其父元素的尺寸变化。这种单位充分利用了可用空间,可以实现自适应设计。介绍如下:
% 是基于父元素的尺寸计算的计算公式:1% = 父元素尺寸的1%示例:
!DOCTYPEhtml
html
head
style
body{
width:800px;
}
div{
width:50%;
}
/style
/head
body
divHello,World!/div
/body
/html
在这个例子中,将 div 的宽度设置为其父元素(body)宽度的一半,即 50%。因此 div 的实际宽度是其父元素宽度的一半:(800 * 50/100)px = 400px
px 自动转换为 vw设计师经常给宽度大小为 375px 或 750px 的视觉稿,单位是 px,手动转换起来就很头疼,所以可以采用社区提供的 postcss-px-to-viewport插件,可以实现将单位 px 自动转换为 vw
安装插件npminstallpostcss-px-to-viewport--save-dev
yarnadd-Dpostcss-px-to-viewport
引入插件我们项目用的是 React 框架 + umi 脚手架,所以参考 umi 官网文档 - API 之配置,使用 extraPostCSSPlugins 这个属性即可引入 postcss-px-to-viewport 插件
参数配置参数配置示例:(其他配置项参考官网)
importpx2vwfrom'postcss-px-to-viewport';
exportdefaultdefineConfig({
extraPostCSSPlugins:[
px2vw({
unitToConvert:'px',//要转化的单位
viewportWidth:750,//视窗的宽度,可根据自己的需求调整(这里是以PC端为例)
//viewportHeight:1080,//视窗的高度
unitPrecision:6,//转换后的精度,即小数点位数
propList:['*'],//指定转换的css属性的单位,*代表全部css属性的单位都进行转换
viewportUnit:'vw',//指定需要转换成的视窗单位,默认vw
fontViewportUnit:'vw',//指定字体需要转换成的视窗单位,默认vw
//selectorBlackList:['wrap'],//指定不转换为视窗单位的类名,
minPixelValue:0.1,//默认值1,小于或等于1px则不进行转换
mediaQuery:false,//是否在媒体查询的css代码中也进行转换,默认false
replace:true,//是否转换后直接更换属性值
exclude:[/node_modules/],//设置忽略文件,用正则做目录名匹配
landscape:false,//是否处理横屏情况
}),
]
});
最终效果.invalid {
width: 100vw;
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
position: fixed;
top: -80px;
left: 0;
font-size: 32px;
}
响应式布局flex 布局?参考 flex 布局的基本概念 - MDN 提供的定义:「Flexible Box 模型」,通常被称为 flexbox,是一种一维的布局模型。它给 flexbox 的子元素之间提供了强大的「空间分布」和「对齐能力」。我们说 flexbox 是一种一维的布局,是因为一个 flexbox 一次只能处理一个维度上的元素布局,「一行或者一列」。
?flex 布局的使用可以查阅我以前写的文章:CSS系列 -- flex布局(https://juejin.cn/post/6951657823893717022),在此不作赘述
grid 布局?参考 网格布局 - MDN 提供的定义:「CSS 网格布局」擅长于将一个页面划分为几个主要区域,以及定义「这些区域的大小、位置、层次」等关系。像表格一样,网格布局让我们能够按行或列来对齐元素。然而在布局上,网格比表格更可能做到或更简单。例如,网格容器的子元素可以自己定位,以便它们像 CSS 定位的元素一样,真正的有重叠和层次。
?grid 布局的使用也可以查阅我以前写的文章:CSS系列 -- grid布局(https://juejin.cn/post/6951664889240748062),在此不作赘述
模拟设备测试方案模拟桌面端屏幕尺寸打开 Chrome 浏览器控制台,打开设备工具栏(Ctrl+Shift+M)打开尺寸栏,选择【自适应】,拖动右下角即可随意设置屏幕尺寸宽高,模拟各种桌面端屏幕尺寸非常地简单。同时也可以直接输入宽高,更加精确模拟移动端设备为了模拟多端设备的纵横比,同样可以利用控制台来模拟这些设备
打开尺寸栏,点击【修改】填写设备信息保存设备后即可快速模拟各端的纵横比(这里只举例三个)H5 会变“矮”?细心的同学会发现:「真机测试」时在大多数移动端浏览器和 APP 端内打开的 H5 会变“矮”
这是由于大多数移动端浏览器和 APP 端内有固定高度的「状态栏、标题栏、底部导航栏」,影响了「视口高度」,所以在真机中打开的 H5 的纵横比要「实际小于」上面计算出的纵横比,所以我们也要考虑到状态栏、标题栏、底部导航栏占掉的高度(特别是有「一屏渲染」的需求)
这里我推荐下载安装 微信开发者工具 来模拟真机效果
下载安装后打开微信开发者工具,选择「公众号网页项目」把本地 dev 运行的链接直接贴进去,即可同时看到控制台打印信息和模拟器
自定义模拟器同样的,我们也可以自定义模拟器的配置
可以看到,所有的模拟器「状态栏」、「标题栏」都占用了 H5 的高度
而且当我们选择 「iPhone X 及以上的苹果系统设备」模拟器时,还有苹果系统自带的「底部安全区」占用了 H5 的高度
不同的是:
状态栏和标题栏“挤掉”了 H5 的高度苹果系统自带的底部安全区没有占用 H5 的高度,而是“覆盖”在 H5 上面的,所以我们要给 「iPhone X 及以上的苹果系统」留足一定的安全距离值得一提的是:
安卓系统真机自带的「底部导航栏」也会“挤掉” H5 的高度(这在微信开发者工具的模拟器没有出现),所以不需要 H5 本身去兼容,只需要考虑到高度会变“矮”的情况即可H5 给苹果系统留足安全距离苹果系统中的一个可视窗口范围,受「圆角、齐刘海、小黑条」影响,下图的蓝色区域才是 H5 (当然也包括 APP)的可操作区域:
也就是说,我们必须要保证页面可视、可操作区域到屏幕边界有一定的「安全距离」。更详细说明参考文档:Human Interface Guidelines - iPhoneX
先了解:viewport-fit 属性iOS11 新增特性,苹果公司为了适配 iPhoneX 对现有 「viewport meta 标签的一个扩展」,用于设置网页在可视窗口的布局方式,可设置三个值。
contain: 可视窗口完全包含网页内容(左图)cover:网页内容完全覆盖可视窗口(右图)auto:默认值,跟 contain 表现一致
需要注意:网页默认不添加扩展的表现是 viewport-fit=contain,需要适配 iPhoneX 必须设置 viewport-fit=cover,这是适配的关键步骤。更详细说明,参考文档:viewport-fit-descriptor
先了解:env()、constant() 函数iOS11 新增特性,Webkit 的一个 CSS 函数,用于设定安全区域与边界的距离,有四个预定义的变量:
safe-area-inset-left:安全区域距离左边边界距离safe-area-inset-right:安全区域距离右边边界距离safe-area-inset-top:安全区域距离顶部边界距离safe-area-inset-bottom:安全区域距离底部边界距离这里我们只需要关注 safe-area-inset-bottom 这个变量,因为它对应的就是小黑条的高度(横竖屏时值不一样)。
注意:当 viewport-fit=contain 时 env() 是不起作用的,必须要配合 viewport-fit=cover 使用。对于不支持 env() 的浏览器,浏览器将会忽略它
需要注意的是之前使用的 constant() 在 iOS11.2 之后就不能使用的,但我们还是需要做「向后兼容」,像这样:
padding-bottom:constant(safe-area-inset-bottom);/*兼容iOS11.2*/
padding-bottom:env(safe-area-inset-bottom);/*兼容iOS=11.2*/
注意:env() 跟 constant() 需要「同时存在」,「而且顺序不能换」。更详细说明,参考文档:Designing Websites for iPhone X(https://webkit.org/blog/7929/designing-websites-for-iphone-x/?hmsr=funteas.com&utm_medium=funteas.com&utm_source=funteas.com)
方案新增 viweport-fit 属性,使得页面内容完全覆盖整个窗口metaname="viewport"content="width=device-width,viewport-fit=cover"
通过加内边距 padding 扩展高度:{
padding-bottom:constant(safe-area-inset-bottom);
padding-bottom:env(safe-area-inset-bottom);
}
注意,这个方案需要「吸底条必须是有背景色的」,因为扩展的部分背景是跟随外容器的,否则出现镂空情况。
还有一种方案就是,可以通过新增一个「新的元素」(空的颜色块,主要用于小黑条高度的占位),然后吸底元素可以不改变高度只需要调整位置,像这样:
{
margin-bottom:constant(safe-area-inset-bottom);
margin-bottom:env(safe-area-inset-bottom);
}
空的颜色块:
{
position:fixed;
bottom:0;
width:100%;
height:constant(safe-area-inset-bottom);
height:env(safe-area-inset-bottom);
background-color:#fff;
}
总结开发前:尽可能了解用户画像,包括操作系统(Windows、Mac、iOS、Android?)、访问设备(桌面端、移动端?),尽可能「减少需要兼容的屏幕的范围」开发过程中:采用响应式设计 「viewport」采用媒体查询 「@media」采用自适应单位 「rem、vw、%」 等采用响应式布局 「flex」 布局、「grid」 布局考虑到真机视口高度变“矮”的情况,以及给苹果新系统留足安全距离测试过程中:采用谷歌浏览器的模拟设备采用微信开发者工具模拟设备真机测试参考文章https://juejin.cn/post/7046169975706353701https://www.dowv.com/news/175.htmlhttps://zhuanlan.zhihu.com/p/26232703https://juejin.cn/post/7046269334259236901https://www.runoob.com/css/css-rwd-viewport.html点击关注公众号回复”小册” 优惠券免费领!!
阅读原文
网站开发网络凭借多年的网站建设经验,坚持以“帮助中小企业实现网络营销化”为宗旨,累计为4000多家客户提供品质建站服务,得到了客户的一致好评。如果您有网站建设、网站改版、域名注册、主机空间、手机网站建设、网站备案等方面的需求...
请立即点击咨询我们或拨打咨询热线:13245491521 13245491521 ,我们会详细为你一一解答你心中的疑难。 项目经理在线