pc, 移动端 全设备适配方案, 涉及 rem vw 响应式 自适应

2,845 阅读4分钟

先上结论:

  • 移动端, pc端 需要两个设计图,两套代码
  • 移动端,首选vw单位布局, 其次可选 rem + lib-flexible
  • 对于pc端, 使用px单位

本文不会讲dpi, 设备独立像素, css像素等 各种概念, 只讲落地到代码层面, 你需要知道的知识, 这是一个程序员的自我修养

css代码是如何关联到物理设备的?

不同的电子设备,其物理尺寸,分辨率都不尽相同, 但是css代码的 style.width 总是和设备物理宽度成正相关屏幕尺寸大全, 所以我们可以认为, 只要适配了 style.width, 就适配了所有设备,无论是pc 还是mobile, 至于屏幕高度,我们不用关心, 毕竟页面是上下滚动查看的

如何知道一个设备的 style.width ?

  • window.screen.width : 出厂就固定了, 用户无法调节
  • window.innerWidth: 即css的媒体查询, 用户可以调节, 比如window的屏幕缩放,浏览器设置的缩放,

因此, 你就知道用户有没有缩放过页面:

const isScale = window.screen.width !== window.innerWidth

响应式 vs 自适应

目前存在两种布局方案

  1. 响应式: 预设几个宽度断点,在一段区间内,都使用同一种样式,比如媒体查询
  2. 自适应: 不设断点, 在不同宽度下,使用不同程度的缩放,比如rem,vw scale

响应式设计 · 断点

sm	640px	@media (min-width: 640px) { ... }
md	768px	@media (min-width: 768px) { ... }
lg	1024px	@media (min-width: 1024px) { ... }
xl	1280px	@media (min-width: 1280px) { ... }
2xl	1536px	@media (min-width: 1536px) { ... }

因为最小的ipad尺寸是768, 比如小米平板 2, 所以一般认为 < 768 即是移动端

适配移动端: 只能选择自适应, 没见过有人搞断点的

适配pc时:

方案一: 媒体查询 + px
  • 例如 永劫无间
  • 这种方案视觉效果最好,但是代码量多, 特别是对于定位元素,你需要在每个断点都实现一遍,性价比不高, 开发体验太差,用的人也少
方案二自适应: rem 或者 vw

rem vs vw ?

vw

  • 优点:理解简单,计算简单
  • 缺点: 灵活性低, 比如你想在 > 769px && <1000px时,保持布局不变,超出显示横向滚动条,做不到

rem

  • 灵活性大
  • 计算麻烦, onResize时,需要使用js或者css去实时修改 html.fontSize,
  • 因为font-会继承, 所以所有文字都需要重置font-size

如果你要使用 tailwindcss,更推荐rem, 至于开发阶段(运行时屏幕==设计稿宽度), 1rem设为多少px合适? 可以结合设计图,量一下最小的padding,margin, 这样可以很好的利用tailwindcssclassname, 不使用tailwindcss, 以及没有最小width,最大宽度的限制, 推荐vw

运行时,推荐使用css来设置rem,性能更好,更简单

html{
--designWidth = 1920px;
--unit:100px;
 font-size: calc(100vw / var(--designWidth) * var(--unit));
}

至于开发时,推荐使用 postcss-pxtorem 来简化计算过程,

媒体查询和自适应的差别:

  • 媒体查询, 可能有横向滚动条,当缺失一些断点时, 会显示横向滚动条
  • 自适应, 没有横向滚动条, 同时高度使用rem
img{
 object-fit:cover;
 object-position: center center; // 图片的细节在哪边, 就设置为哪个方向
}

.bg{
 background-position: center center
}

移动端

需要根据设备宽度实时调整元素大小, 其实就是缩放,但不能使用scale,因为scale会导致 宽高都放大, 而我们一般只需要放大宽度, 因此使用rem 或者 vw

比如设计稿是750像素, 隐含条件是dpr =2,使用rem vs vw ?

  • rem: 需要考虑屏幕dpr, 默认html.fontSize = 16px, 250 / 16 = 15.625 rem
  • vw: 不要考虑dpr, 100/750 * 500 vw, (推荐)

更推荐使用vw, 不用考虑dpr,而且还原度和计算都很简单, 可以搭配postcss-px-to-viewport 使用

如果就要使用rem单位时, 因为移动端涉及不同的dpr, 所以可以使用lib-flexible来辅助计算, 该库写死了

var dpr = window.devicePixelRatio || 1

// set 1rem = viewWidth / 10
  function setRemUnit () {
    var rem = docEl.clientWidth / 10
    docEl.style.fontSize = rem + 'px'
  }

开发时的viewWidth,就是设计稿宽度 / dpr

没用过该库, 如果不是这样,请指正, 可以参考我猜很多人只是会配置,但不明白 postcss-pxtorem 中的 rootValue 配置项是什么意思

// 750设计稿
postCssPxToRem({
    rootValue: 37.5,//  750 / 2 / 10
})

  1. 根据经验设置基于vw等viewport视区单位配合rem响应式排版和布局 750 对应 16px, 没办法完全还原, 适合在小说等文字很多的业务场景
html {
    font-size: 16px;
}

@media screen and (min-width: 375px) {
    html {
        /* iPhone6的375px尺寸作为16px基准,414px正好18px大小, 600 20px */
        font-size: calc(100% + 2 * (100vw - 375px) / 39);
        font-size: calc(16px + 2 * (100vw - 375px) / 39);
    }
}
@media screen and (min-width: 414px) {
    html {
        /* 414px-1000px每100像素宽字体增加1px(18px-22px) */
        font-size: calc(112.5% + 4 * (100vw - 414px) / 586);
        font-size: calc(18px + 4 * (100vw - 414px) / 586);
    }
}
@media screen and (min-width: 600px) {
    html {
        /* 600px-1000px每100像素宽字体增加1px(20px-24px) */
        font-size: calc(125% + 4 * (100vw - 600px) / 400);
        font-size: calc(20px + 4 * (100vw - 600px) / 400);
    }
}
@media screen and (min-width: 1000px) {
    html {
        /* 1000px往后是每100像素0.5px增加 */
        font-size: calc(137.5% + 6 * (100vw - 1000px) / 1000);
        font-size: calc(22px + 6 * (100vw - 1000px) / 1000);
    }
}