加入公司以来,都是参与已有旧项目的功能迭代和维护,一直没有从0到1搭建过一个项目。所以每次接到一个需求之后就机械化的当切图仔(量ui稿尺寸,还原)根据ui稿还原页面和功能。
有时候会注意到,都是需要做响应式开发,有的项目运行后还是px,有的项目则会转成rem,或者vw单位。
而且视觉上差不多大小,有的项目ui稿单位的单位很大,而有的则正常。比如一个视觉上看着一样大小的字体,在这A项目里面量出来上12px,B项目里面量出来就变成了24px,然后最后页面上呈现的效果又是一样的大小。
疑问
- 为什么不同UI稿之间为什么量相同大小的组件(px)大小为什么会有差距。
- 为什么有的项目会将单位转成
rem,有的项目转成vw,有的则保持px。 - 我构建项目的时候该如何去选择单位(
px,rem,vw)去做响应式开发以及以及不同的设计稿我该如何还原?
研究
疑问1
对于疑问1,之前一直有一个误区:
css单位的px===设计稿上的px
而其实仔细想想就能发现,设计稿的的大小是固定的,而用户的屏幕大小则不固定,那么实际稿(固定)大小是多少呢?
回过头去看发现,A项目设计稿总宽度为375px,而B项目设计稿宽度则为750px,欸...这不刚好两倍关系吗?那么其实A项目设计稿的1px是等于B项目设计稿的2px,所以打开页面A项目应该在375px屏幕尺寸下看才能完整还原设计稿。
疑问2,3
要搞清楚项目如何选择px,rem,vw等单位,那么首先应该搞清楚他们原理。
了解了真相,你才能得到真正的自由![旺柴]
看到这些单位,其实作用都清楚,响应式布局,说说都是如何做的?
1. px
css基础单位,不具备响应式能力,但是可以结合另一个可能会忽略的布局%,基本组件固定px+%布局实现自适应。
比如类似下面这种布局方式,组件不随屏幕大小变化而响应式变化,但是页面整体内容不会因为屏幕尺寸改变打乱布局,我总结了一下必须满足下面条件(欢迎补充)
- 没有比如flex,grid之类的多列自适应的布局(布局大小不会改变内部组件尺寸和间距)
2. rem
rem: 相对于根元素的字体大小。例如:
html { font-size: 16px; }
div { width: 10rem; } /* 10rem = 160px */
核心原理,只要根据根元素font-size随屏幕的宽度变化,页面所有使用rem的元素都会按照比例缩放,实现全部元素响应式。
移动端响应式关键原因
移动端屏幕差异大:
- iPhone SE 320px
- iPhone 13 390px
- iPad 768px
如果直接用 px,布局固定,低分辨率小屏幕会溢出,高分辨率大屏幕显得小。
现在常用的计算公式:
屏幕宽度
Html font-size = -------------
10
例如根据上面提到的A项目375px的设计稿
实现有两种方案:
- js动态计算
function setRemUnit () {
var rem = docEl.clientWidth / 10
docEl.style.fontSize = rem + 'px'
}
setRemUnit()
- css媒体查询(固定区间)
html { font-size: 16px; }
@media (max-width: 375px) {
html { font-size: 14px; }
}
@media (min-width: 376px) and (max-width: 768px) {
html { font-size: 18px; }
}
接下来再通过postcss-pxtorem将px转换为rem
{
rootValue: 37.5,
unitPrecision: 5,
propList: ['*'],
selectorBlackList: [],
replace: true,
mediaQuery: false,
minPixelValue: 0,
exclude: /node_modules/i
}
如上面根据postcss-to-rem将375px设计稿转换逻辑和上面公式差不多,比如一个12px的尺寸,转换rem后
12
--------------- = 0.32rem
37.5
实验一下:
.container {
font-size: 12px;
width: 150px;
height: 150px;
background: skyblue;
display: flex;
justify-content: center;
align-items: center;
color: aliceblue;
}
这里用font-size12px来计算,
12 / 37.5 = 0.32rem
结果,符合预期。
这样rem + js的响应式方案就完整了。
3. vw
vw是视口百分比, 1vw = 视口宽度的1%。
转换公式
px
px -> vw = ------------- ✖️ 100px
设计稿宽度
那用vw相比rem做响应式开发就变得非常简单了,不需要js计算,不需要媒体查询,和postcss-to-viewport计算逻辑完美契合,一步到位,轻松实现响应式开发。
{
unitToConvert: 'px', // 原始单位
viewportWidth: 375, // 设计稿尺寸
unitPrecision: 5, // 保留5位小数
propList: ['*'],
viewportUnit: 'vw', // 转换后的视口单位
fontViewportUnit: 'vw', // 转换后的字体单位
selectorBlackList: [],
minPixelValue: 1,
mediaQuery: false,
replace: true,
exclude: undefined,
include: undefined,
landscape: false
}
配置完成之后启动项目。
总结
rem和vw都是实现响应式布局的,px需要结合%实现响应式布局。
区别:
px+%只能实现布局响应式,页面内元素不会随屏幕大小发生变化而变化。
优点: 任何屏幕尺寸下都能保证页面内组件和设计稿的完整还原。
缺点: 有局限性, 如上。
rem和vw则是布局和页面元素都会随屏幕变化而响应式变化。
优点:没有对布局的局限性,任何场景都能用。
缺点: 在移动端横屏情况下字体和元素会拉升的比较大,不协调(其实就是不可用,在移动端横屏和平板情况下)。
---------------------补充---------------------
rem之前常用flexible.js来定制根元素fontsize,目前也不建议推荐使用,建议使用viewport方案。因此,在rem和vw选择上,直接使用vw即可。