先上结论:
- 移动端, 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 自适应
目前存在两种布局方案
- 响应式: 预设几个宽度断点,在一段区间内,都使用同一种样式,比如媒体查询
- 自适应: 不设断点, 在不同宽度下,使用不同程度的缩放,比如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, 这样可以很好的利用tailwindcss的classname,
不使用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
})
- 根据经验设置基于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);
}
}