移动端适配方案总结(二)

简介: 由于自己太久没开发移动端的页面,个人觉得移动端开发相比较PC端开发最大的不同,在于需要去适配各种尺寸的手机屏幕,尤其还有1px的问题。

方案


这些兼容方案都是基于视口不缩放配置才能生效:


目前市面主流的几种适配方案如下:

  • rem ,通过一个宽度尺寸作为统一的单位值,然后通过js计算出不同尺寸对比值,得到适配效果
  • vw ,一个浏览器支持的单位,利用 CSS 视窗的特性,总宽度为 100vw,每一份为一个单位 1vw,设置 1rem 单位为 10vw
  • px + calc + clamp,大漠在2021年提出,根据 CSS 的新特性:css变量、calc()函数、clamp()、@container函数实现

rem方案


rem是指的html元素的font-size的大小,如:html{font-size:50px}; 1rem=50px

实现原理


通过一个具体的例子,更好理解它的原理。比如你拿到一张设计稿为750px宽度的,里面有个长方形为100*200,这个时候需要在不同屏幕去做适配。


rem的解决方案思路为:

  • 将标准尺寸宽度 750/10= 75px,设置:html{font-size:75px} 1rem=75px
  • 将长方形的 100*200,100/75 * 200/75,设置为:.rectangle{width: 1.33rem;height:2.66rem}
  • 那么当屏幕的尺寸发生变话的时候, 变成从750减少为375,那么这个时候,设置: html{font-size:37.5px} 1rem=37.5px
  • 长方形的css设置无需变化,从而达到适配的效果

所以rem的解决方案就是在web应用在加载的时候,提前计算好rem单位,所以就可以完成适配。


目前主流的方案有:


源码实现:

h5-shipei.js


PS: 里面涉及到pageshow事件,基本上是因为移动端缓存了web页面,当浏览器历史记录前进或后退的是会触发,可以通过e.persisted判断是否从缓存获取


缺点:

  • 需要前置js才能实现,根据设备的视窗宽度进行计算,影响性能
  • 在 PC 端浏览破相,一般设置一个最大宽度

vw方案


是什么


vw是css的一种计算单位,定义:

1vw 等于1/100的视口宽度 (Viewport Width)

同理vh也是:

1vh 等于1/100的视口高度 (Viewport Height)

那么vmax,vmin,我在网上找到比较好解释如下:

vmin — vmin的值是当前vw和vh中较小的值。 vmax — vw和vh中较大的值。 在横竖屏的切换中,十分有用。

原理


了解到vw的概念,那么如何利用vw去解决移动端的适配呢?其实和rem方案是一样,具体代码可以如下:

/* rem 方案 */
html { font-size: width / 100}
div { width: 26.67rem }
/* vw 方案 */
div { width: 26.67vw }

已实现的框架方案如下:

postcss-px-to-viewport

利用打包编译过程,将设置好的px单位转换为vw或vh,具体使用可以看使用文档。

缺点:

  • 和rem一样,容易在pc端适配错误,可以用@media媒体查询去做样式兼容

后续添加


如果利用flex/grid布局,加上vw、vh单位,是否可以做到自适应布局呢?


答案是肯定,而且相对而言会比其他方案,会更加容易开发些,实现步骤如下:

  • 利用flex弹性布局,加上vw设置flex弹性盒子的宽度,从而做到不同宽度屏幕,是否换行或者垂直布局


后续可以专门写个文章用来描述flex布局的原理。

px + calc + clamp


是什么


calc() 此 CSS 函数允许在声明 CSS 属性值时执行一些计算。 支持  + , - , / ,* 等运算。

/* property: calc(expression) */
width: calc(100% - 80px);

clamp() 函数的作用是把一个值限制在一个上限和下限之间,当这个值超过最小值和最大值的范围时,在最小值和最大值之间选择一个值使用。它接收三个参数:最小值、首选值、最大值。

font-size: clamp(1rem, 2.5vw, 2rem); 
  • 2.5vw大于2rem,使用2rem
  • 2.5vw小于1rem,使用1rem
  • 其他使用2.5vw单位

原理


了解到上面css两个函数,如果通过只用px单位去做适配呢?原理步骤如下:

  • 假设我们拿到的设计稿750px宽度,那么这个时候有个长方体是200*100
  • 利用css变量,设置一个首先值,然后计算出去其他尺寸所需的最大值、最小值,设置clamp()
  • 同时利用calc()去计算偏差值


缺点:

  • calc 和clamp 函数在浏览器支持度还不够
  • 需要了解这套方案还需要较深的技术方案

1px高清显示问题


1像素问题: 1像素指在 Retina 屏显示 1单位物理像素

  • DPR = 1,此时 1 物理像素 等于 1 CSS 像素
  • DPR = 2,此时 1 物理像素等于 0.5 CSS 像素
  • border-width: 1px,这里的 1px 其实是 1 CSS 像素宽度,等于 2 物理像素,设计师其实想要的是 border-width: 0.5px DPR = 3,此时 1 物理像素等于 0.33 CSS 像素。设计师想要的是 border-width: 0.33px


解决方案:

  • 渐变实现 : background-image: linear-gradient(to top, ,,,)
  • 使用缩放实现:transform: scaleY(0.333)
  • 使用图片实现:base64
  • 使用 SVG 实现:嵌入 background url
  • border-image,低端机下支持度不好


以上方案都是基于媒体查询解决的

@media only screen and (-webkit-min-device-pixel-ratio: 2),
    only screen and (min-device-pixel-ratio: 2) {}
@media only screen and (-webkit-min-device-pixel-ratio: 3),
    only screen and (min-device-pixel-ratio: 3) {
}

媒体查询


媒体查询(Media queries)非常实用,尤其是当你想要根据设备的大致类型(如打印设备与带屏幕的设备)或者特定的特征和设备参数(例如屏幕分辨率和浏览器视窗宽度)来修改网站或应用程序时。

使用


一般有几种用法,如下所示:

  • 通过 @media@import at-rules 用CSS 装饰样式
  • media= 属性为, <link>, <source></code>和其他HTML元素指定特定的媒体类型</li><li>使用<code>Window.matchMedia() </code>和 <code>MediaQueryList.addListener()</code> 方法来测试和监控媒体状态</li></ul><div><br /></div><div>CSS装饰样式用法</div><div data-card-type="block" data-ready-card="codeblock" data-card-value="data:%7B%22mode%22%3A%22plain%22%2C%22code%22%3A%22%40media%20screen%2C%20print%20%7B%20...%20%7D%22%2C%22heightLimit%22%3Atrue%2C%22margin%22%3Atrue%2C%22id%22%3A%22kTugZ%22%2C%22autoWrap%22%3Atrue%7D"></div><div>HTML元素引入</div><div data-card-type="block" data-ready-card="codeblock" data-card-value="data:%7B%22mode%22%3A%22plain%22%2C%22code%22%3A%22%3Clink%20rel%3D%5C%22stylesheet%5C%22%20src%3D%5C%22styles.css%5C%22%20media%3D%5C%22screen%5C%22%20%2F%3E%5Cn%3Clink%20rel%3D%5C%22stylesheet%5C%22%20src%3D%5C%22styles.css%5C%22%20media%3D%5C%22print%5C%22%20%2F%3E%22%2C%22heightLimit%22%3Atrue%2C%22margin%22%3Atrue%2C%22id%22%3A%22V8UsP%22%2C%22autoWrap%22%3Atrue%7D"></div><div>js用法</div><div data-card-type="block" data-ready-card="codeblock" data-card-value="data:%7B%22mode%22%3A%22plain%22%2C%22code%22%3A%22let%20mql%20%3D%20window.matchMedia('(max-width%3A%20600px)')%3B%5Cndocument.querySelector(%5C%22.mq-value%5C%22).innerText%20%3D%20mql.matches%3B%5Cn%5Cnvar%20mql%20%3D%20window.matchMedia('(max-width%3A%20600px)')%3B%5Cn%5Cnfunction%20screenTest(e)%20%7B%5Cn%20%20if%20(e.matches)%20%7B%5Cn%20%20%20%20%2F*%20the%20viewport%20is%20600%20pixels%20wide%20or%20less%20*%2F%5Cn%20%20%20%20para.textContent%20%3D%20'This%20is%20a%20narrow%20screen%20%E2%80%94%20less%20than%20600px%20wide.'%3B%5Cn%20%20%20%20document.body.style.backgroundColor%20%3D%20'red'%3B%5Cn%20%20%7D%20else%20%7B%5Cn%20%20%20%20%2F*%20the%20viewport%20is%20more%20than%20than%20600%20pixels%20wide%20*%2F%5Cn%20%20%20%20para.textContent%20%3D%20'This%20is%20a%20wide%20screen%20%E2%80%94%20more%20than%20600px%20wide.'%3B%5Cn%20%20%20%20document.body.style.backgroundColor%20%3D%20'blue'%3B%5Cn%20%20%7D%5Cn%7D%5Cn%5Cnmql.addListener(screenTest)%3B%22%2C%22heightLimit%22%3Atrue%2C%22margin%22%3Atrue%2C%22id%22%3A%22Y69w3%22%2C%22autoWrap%22%3Atrue%7D"></div><h1 id="xUab1">图片高清问题</h1><div data-card-type="block" data-ready-card="hr"></div><div>图片高清问题,一般是指的:不同 DPR 下图片的高清解决方案。</div><div>这种问题解决方案,通常是利用媒体查询+提供不同尺寸的图片去显示。</div><h1 id="q0hab">总结</h1><div data-card-type="block" data-ready-card="hr"></div><div>移动端适配方案,结合开发中,大家都是直接写px,然后利用编译过程的进行转换,比如: <code>px2rem</code> ,<code>px2vw</code>。</div><div>再就是排版问题,不同屏幕问题需要做自动排版优化方案,这个需要后面去研究一下<a href="https://link.juejin.cn?target=https%3A%2F%2Fnews.sangniao.com%2Fp%2F1729687518" target="_blank" ref="nofollow noopener noreferrer">《如何正确的使用 CSS Clamp 进行响应式排版》</a>。</div>
目录
相关文章
|
2月前
|
编解码 前端开发 JavaScript
前端移动端适配方案
【9月更文挑战第8天】前端移动端适配方案
76 0
|
3月前
|
前端开发 小程序
移动端适配方案
【8月更文挑战第1天】
|
3月前
|
Web App开发 前端开发
什么是移动端适配
【8月更文挑战第2天】
|
3月前
|
前端开发
移动端适配问题
【8月更文挑战第6天】
53 4
|
3月前
|
前端开发 JavaScript
移动端适配
【8月更文挑战第4天】
39 4
|
6月前
|
Web App开发 编解码 前端开发
如何做移动端适配?
如何做移动端适配?
61 0
|
JavaScript
深入了解移动端适配的方案
深入了解移动端适配的方案
249 0
|
编解码 前端开发 JavaScript
前端移动端优化和适配
前端移动端优化和适配
201 0
|
编解码 前端开发
移动端适配方案总结(一)
由于自己太久没开发移动端的页面,个人觉得移动端开发相比较PC端开发最大的不同,在于需要去适配各种尺寸的手机屏幕,尤其还有1px的问题。
160 0
|
JavaScript 前端开发 异构计算
大屏适配方案汇总
大屏适配方案汇总
大屏适配方案汇总