自适应布局方案[转]

自适应布局方案

一套代码对应一份设计稿,实现向上/向下兼容自适应布局方案对比

这里只做最表面的使用方法。不对,不进行多种环境(复杂布局等)的测试,内容仅供参考。

后续会对每一个方案做进一步的研究。你问我什么时候?下次一定!👾

起步

rem 是什么

rem(font size of the root element)是指相对于根元素<html>来做计算的字体大小单位。

e.g. 设置html { font-size: 75px }时,其他元素1rem = 75px4rem = 300px

vw 是什么

vw是基于viewport视窗的长度单位。1vw等于window.innerWidth1%

e.g. 设备物理宽度为375px时,1vw = 3.75px

dpr 是什么

设备像素比device pixel ratio简称dpr,即物理像素和设备独立像素的比值。

web中,浏览器为我们提供了window.devicePixelRatio来帮助我们获取dpr

iPhone 6、7、8的实际物理像素是750 x 1334,在开发者工具中我们可以看到:它的设备独立像素是375 x 667,设备像素比dpr2

e.g. 如果给定一个元素的高度为200px(这里的px指物理像素,非CSS像素),iphone6的设备像素比dpr = 2,我们给定的height应为200px/2=100dp

postcss-px-to-viewport(饿了么移动端做法)

postcss-px-to-viewport的做法其实没多大不同,它直接计算每个像素在设计稿中占据的%来输出vwrem

设计稿 = 375px 时

1. 转换 VW 方案

'postcss-px-to-viewport': {
    unitToConvert: 'px', // 需要转换的单位,默认为"px"
    viewportWidth: 375, // 视窗的宽度,对应设计稿的宽度
    viewportUnit: 'vw', // 指定需要转
    fontViewportUnit: 'vw', // 字体使用的视口单位
    unitPrecision: 13 // 指定`px`转换为视窗单位值的小数后 x位数
    ...
}
复制代码

计算 1px 在设计稿中的占比,再换算成 vw

1px = 1 / 375 = 0.2666666666666%100px = 26.6666666666666% = 26.6666666666666vw

实际渲染时(375px 的屏幕),26.6666666666666vw = 26.6666666666% * 375 = 100px

[图片上传失败...(image-193cc1-1649317373021)]

在 转换成vw的方案设置媒体查询超出宽度范围后固定body宽度,内容居中时,会出现样式过大影响查看的问题。

@media screen and (min-width: 1024px) {
  html {
    max-width: 1024px;
  }
}
复制代码

[图片上传失败...(image-7e7cf0-1649317373021)]

2.转换 REM 方案

避免不同浏览器的默认字体大小不一样导致大小不一致的问题,我们需要固定好root元素 htmlfont-size

恰好我们可以利用postcss-px-viewport不支持内联样式的转换。来设置root元素 html的内联font-size: 16px;来固定root的字体大小以适配转换成rem的方案。

1px = 1 / 375 = 0.2666666666666%100px = 26.6666666666666% = 26.6666666666666rem

由于我们设置了root元素 html的内联font-size: 16px;来固定root的字体大小。因此,实际渲染时(375px 的屏幕),容器26.6666666666666rem = 26.6666666666666 * 16 = 426.6666666666656px

也就是说,我们需要更改viewportWidth的大小来和设计图适配。直接推导一下设计图与viewportWidth的倍数关系 = 426.6666666666656 / 100 = 4.26656倍。设置viewportWidth: 1599.96 (375 * 4.26656 = 1599.96)

[图片上传失败...(image-f17b5b-1649317373021)]

同样设置媒体查询超出宽度范围后固定body宽度,内容居中

@media screen and (min-width: 1024px) {
  html {
    max-width: 1024px;
  }
}
复制代码

[图片上传失败...(image-fb041b-1649317373021)]

rem + vw(网易移动端做法)

原则上也需要一个参考的设计图,这边假设为375px宽设计图。计算方法与postcss-px-to-viewport rem方案一至。

计算公式 :1vw = 3.75px 1px = 0.2666666666666667vw 100px = 26.6666666666666667vw

1rem = 26.6666666666666667vw = 100px

但需要注意的是,设置时需要把1rem设置成100px 对应的 vw值的值(防止小于浏览器最小字体),编写时根据设计图px / 100来编写。

当需要向上兼容自适应的时候,设置好@media对应不同的font-size即可。

同样设置媒体查询超出宽度范围后固定body宽度,内容居中。

html {
  font-size: 26.6666666666666667vw;
  margin: 0 auto;
  body {
    // 重置字体大小
    font-size: 0.14rem;
  }
}

@media screen and (min-width: 768px) {
  html {
    font-size: 9vw;
    max-width: 768px;
  }
}
复制代码

[图片上传失败...(image-970363-1649317373019)]

Flexible(前手淘做法)

js 获取clientWidth,分成十份。再设置rem。字体大小则是12 * dpr

引用大漠老师的话:

由于viewport单位得到众多浏览器的兼容,lib-flexible这个过渡方案已经可以放弃使用,不管是现在的版本还是以前的版本,都存有一定的问题。建议大家开始使用viewport来替代此方案。vw的兼容方案可以参阅《如何在Vue项目中使用vw实现移动端适配》一文。

原理放到现在也很好理解。根据设备屏幕的DPR,自动设置最合适的高清缩放(body的字体大小,重置根目录的字体大小)。width=设备独立像素的宽度,初始/最大/最小缩放=1。通过 js计算root fontSize的值,使1rem = 设计稿 / 10。

既然都说可以放弃使用,那就不展示了。

源码地址github.com/amfe/lib-fl…

总结

Flexible在当今已经可以放弃掉,转用 CSS的方法解放因使用JS动态修改fontsize所消耗的性能

只做移动端

postcss-px-to-viewport -- vw方法

一把梭,什么都不用考虑。且是最真实的按照屏幕大小的比例来放大缩小。

小屏设计图向上兼容自适应大屏幕

当需要从移动端设计图适配到平板PC屏幕

(最方便)postcss-px-to-viewport -- rem

优点

  1. 自动转换 UI框架中的单位。
  2. 配合media媒体查询设置root fontSize适配不同分辨率的大小以及限制最大宽度

缺点

  1. 所有设置转换的单位都会被转换掉,无法设置某些样式的单位不被转换。

(最灵活)rem + vw

优点

  1. 配合media媒体查询设置root fontSize适配不同分辨率的大小以及限制最大宽度。
  2. 高度自定义,谁需要转换谁转换成rem

缺点

  1. 当需要把 UI框架中的单位也转换时,会非常的头大。需要一个一个覆盖。

(不适合)postcss-px-to-viewport -- vw

该方案在限制最大宽度的时候,由于大小都是更具 viewport来决定的。所以限制了最大宽度时里面的内容依旧会随viewport变大而变大。故不合适

大屏设计图向下兼容自适应小屏幕

(建议)postcss-px-to-viewport -- rem

优点

  1. 自动转换 UI框架中的单位,省事。
  2. 设置最小宽度居中,超出部分滚动条。
  3. 适配比设计稿更大的屏幕时把root fontSize设置为更大即可。

缺点

  1. 所有设置转换的单位都会被转换掉,无法设置某些样式的单位不被转换。

(一般) rem + vw

假设屏幕 1024px

计算公式 :1vw = 10.24px 1px = 0.09765625vw 100px = 9.765625vw

1rem = 9.765625vw = 100px

优点

  1. 设置时需要把1rem设置成100px 对应的 vw值的值(防止小于浏览器最小字体),编写时根据设计图px / 100来编写。

缺点

  1. 需要写多个媒体查询更改root fontSize(因为存在字体太大导致一屏内容显示太少问题)。
  2. 当需要把 UI框架中的单位也转换时,会非常的头大。需要一个一个覆盖。
  3. 无法设置最小宽度居中内容。

(不适合)postcss-px-to-viewport -- vw

由于国产浏览器中的root fontSize小于默认最小字体(一般是 12px)时,会强制保持root fontSize = 12px ,因此该方法并不适合。

demo仓库地址

博客链接: github gitee

作者:Mirai白
链接:https://juejin.cn/post/6867874227832225805
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,524评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,869评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,813评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,210评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,085评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,117评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,533评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,219评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,487评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,582评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,362评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,218评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,589评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,899评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,176评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,503评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,707评论 2 335

推荐阅读更多精彩内容