px、em、rem的区别
px: 一个盒子是100px * 100px px指的是逻辑像素,也叫css像素 在适配时,使用px作为单位并不合适。 em: 指的是一个汉字的宽度,2em表示两个汉字的宽度 1em = 1个font-size的大小 如:font-size:20px; 1em = 20px 10em = 200px
em不足:它是相对于父元素的font-size来说的。
适配使用em也不合适,因为它一直是相对于父元素的font-size来说的
rem:
r表示root root是根的意思 指html标签
1rem ==> html标签中的font-size的大小
1em ==> 父标签中的font-size的大小
如:html标签的font-size设置成了34px
1rem = 34px
2rem = 68px
3rem = 102px
什么是适配
适配: 在大屏上显示大盒子,在小屏上显示小盒子。
什么是适配? 如果是大屏,盒子或字体大上设置的大一点 如果是小屏,盒子或字体大小设置的小一点
实现适配
通过媒体查询实现适配
使用媒体查询,实现适配:媒体查询 类似于 编程语言中的if-else
我有一张设计图,一行文字,10个字,在750屏上,是撑满一行的。 还有一张图片,占手机屏的一半。 需要利用媒体查询+rem来适配,步骤如下:
-
得到设计稿 一般情况下,设计稿的尺寸是750px。
-
通常我们把浏览器的模拟器也调整成750px
-
严格按照设计稿,以rem为单位,把设计稿还原出来。
-
开始写样式,需要确定html标签的font-size,通常我会把fontsize 定成100px,叫rem的基准值。
有一个盒子,width是20px 1rem = 100px。 盒子是20px 换成rem 换成0.2rem
有一个盒子,width是20px 1rem = 100px。
盒子是20px换成rem 换成0.2rem
又量出一个盒子的宽度是55px,换成rem就是0.55rem。
说白了,量设计稿,量出来的Px单位,只需要除于100,就成rem单位
到此,你先不要管适配,你就在750px的屏上,还原750的设计稿。
- 最后一步,把写好的页面,迁移到其它屏上的,完成适配。 在迁移时,也需要换算。 换算如下: 在750px的屏上,html的font-size的大小为100px。 在375px的屏上,html的font-size的大小为50px。 在320px的屏上,html的font-size的大小为42.6666666px。 在414px的屏上,html的font-size的大小为55.2px。
如果使用媒体查询+rem来适配,需要写如下代码:
@media only screen and (width:375px) { html{ font-size: 50px; } }
@media only screen and (width:320px) { html{ font-size: 42.6666px; } }
@media only screen and (width:414px) { html{ font-size: 55.2px; } }
// ....
// ....
// ....
如果我们写要适配的屏比较多,那么我们需要写大量的媒体查询的代码。
JS+rem适配
JS+rem来适配,步骤如下:
let docEle = window.document.documentElement; //表示获取窗口
//该函数用来计算不同屏的html标签的font-size
function refresh(){
let width = docEle.getBoundingClientRect().width //一屏的宽度
if(width>750){ width=750 }
let fs = width / 7.5
document.querySelector("html").style.fontSize= fs + "px"
}
refresh();
//window表示事件源 addEventListener用来绑定事件的
//resize叫浏览器窗口大小改变事件 ()=>{}叫事件监听器
window.addEventListener("resize",()=>{
refresh()
})
//pageshow 页面显示出来
window.addEventListener("pageshow",()=>{
refresh()
})
</script>
优点:
rem单位是根据根元素font-size决定大小,只要改变font-size的值,以rem为固定单位的元素大小也会发生响应式的改变
缺点:
必须通过一段js代码控制font-size的大小 控制font-size的js代码必须放在在页面第一次加载完成之前,并且放在引入的css样式代码之前。
百分比布局适配
百分比布局方案:给元素设置百分比,例如2个div想占满宽度100%,那么一个div设置宽度为50%,这样不固定宽度,使得在不同的分辨率下都能达到适配 那么需要清楚一个问题,各个子元素或属性的百分比是根据谁来设定呢?
子元素width、height的百分比:子元素的width或height中使用百分比,是相对于子元素的直接父元素 margin和padding的百分比:在垂直方向和水平方向都是相对于直接父亲元素的width,而与父元素的height无关 border-radius的百分比:border-radius的百分比是相对于自身宽度,与父元素无关
优点:
宽度自适应,在不同的分辨率下都能达到适配
缺点:
百分比的值不好计算 需要确定父级的大小,因为要根据父级的大小进行计算 各个属性中如果使用百分比,相对父元素的属性并不是唯一的 高度不好设置,一般需要固定高度。
vw、vh方案
css3中引入与视口有关的新的单位vw和vh,vw表示相对于视口的宽度,vh表示相对于视口高度
| 单位 | 含义 |
|---|---|
| vw | 相对于视口的宽度,视口宽度是100vw |
| vh | 相对于视口的高度,视口宽度是100vh |
| vmin | vw和vh中较小的值 |
| vmax | vw和vh中较大的值 |
vw单位换算: 视口宽度为100vw占满整个视口区域,那么1vw相当于占整个视口宽度的1%,所以1px= 1/375*100 vw 所有的页面元素都可以直接进行计算换算成vw单位,但是这样计算和百分比方案计算比较类似,都会比较麻烦。 但是可以利用一款插件得到解决—— postcss-px-to-viewport,可以预处理css,将px单位转换为vw单位,但是需要进行一些相关的webpack配置
loader: 'postcss-loader',
options: {
plugins: ()=>[
require('autoprefixer')({
browsers: ['last 5 versions']
}),
require('postcss-px-to-viewport')({
viewportWidth: 375,
viewportHeight: 1334,
unitPrecision: 3,
viewportUnit: 'vw',
selectorBlackList: ['.ignore', '.hairlines'],
minPixelValue: 1,
mediaQuery: false
})
]
}
复制代码接下来是对postcss-px-to-viewport配置中的属性的介绍:
| 单位 | 含义 |
|---|---|
| viewportWidth | 视口宽度(数字) |
| viewportHeight | 视口高度(数字) |
| unitPrecision | 设置的保留小数位数(数字) |
| viewportUnit | 设置要转换的单位(字符串) |
| viewportUnit | 设置要转换的单位(字符串) |
| selectorBlackList | 不需要进行转换的类名(数组) |
| minPixelValue | 设置要替换的最小像素值(数字) |
| mediaQuery | 允许在媒体查询中转换px(true/false) |
优点:
指定vw\vh相对与视口的宽高,由px换算单位成vw单位比较简单 通过postcss-px-to-viewport插件进行单位转换比较方便
缺点:
直接进行单位换算时百分比可能出现小数,计算不方便 兼容性- 大多数浏览器都支持、ie11不支持 少数低版本手机系统 ios8、android4.4以下不支持
总结
对于上述的各种移动端web页面自适应方案来说,都存在着一些优势和不足,具体使用哪种方案要依据实际情况。通过查看一些知名网页的源代码我发现,在移动端适配上它可能不是某一种方案的单独使用,而是几种方案的结合。一个页面上,元素的宽度设置上有百分比,也有rem,字体的样式中有rem,有em,也有固定大小的px;在屏幕宽度过大时不再缩放,也会用到媒体查询,并且响应式设计更多地可能是针对不同设备间的自适应。对于移动端web页面的自适应方案来说,当今最流行和用的最多的还是rem布局方案。