前言
最近几年都是基于PC在开发,突然要搞移动端有点不适应,主要还是处理各终端的适配.我们通常开发的页面在PC浏览器上显示正常,但是如果放在窄屏设备(移动设备)上,会在比屏幕宽的虚拟窗口或者视口中呈现页面,以便让用户可以一次性看到所有内容,用户可以通过平移缩放查看不同区域,这是没有进行移动优化的页面,它的体验是很不好的,或者说看起来很差.
后来,使用媒体查询
,进行一些优化.但仍然存在问题,比如无法或者说很难做到更细的窗口变化体验.只能是一个区间来控制.
meta和viewport
简单的说viewport
就是浏览器的窗口宽度高度.但是在移动端就变得复杂了,移动端的viewport宽度高度都变小,做布局需要用到两个viewport
: viewportvisualviewport
(虚拟的viewport)和viewportlayoutviewport
(布局的viewport).
我们在针对移动设备优化的网站需要有以下内容:
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />
这里的width与height
来控制视口的大小.可以将它设置为特定的像素(例如width = 666
).这边设置为device-width(也有device-height)
,表示CSS像素的屏幕宽度,缩放比例为100%.initial-scale
控制页面首次加载是的缩放级别,maximum-scale,minimum-scale和user-scalable
属性控制用户如何/是否允许缩放页面。
比如我们平时开发UI给的设计图一般按照iphone6的尺寸也就是 375.这时候我们可以设置width=375, initial-scale=1
.这样子可以精确的适应这个尺寸的设备.但是如果有其他的尺寸的话,就会出现问题...这里是各种设备的尺寸参考
rem or em
em
是一个长度单位.表示相对于父级文本的字体尺寸.如果父级字体没有设置尺寸,那就相对于浏览器默认尺寸font-size: 16px
.它的值不是固定的,可以继承父级字体尺寸
.
元素的width/height/line-height/padding/margin用em为单位都是是相对于该元素的font-size
.div1 {font-size: 16px;}
.div2 {font-size: 2em;height: 2em;}
.div3 {font-size: 2em;}
<div class="div1"> // font-size: 16px;
<div class="div2">1</div> // font-size: 32px;height: 64px;
<div class="div3">1</div> // font-size: 32px;
</div>
rem
是css3的相对单位.它设置的字体元素相对的是HTML根元素.也就是说我们设置html页面跟元素的font-size
, 那项目里的其他节点使用rem
这个单位去换算,都会依照这个根元素的值.
其实它就是基于宽度的等比缩放.比如我们将屏幕平分100份,那我们如果知道屏幕宽度,然后去换算出来1份的宽度.然后我们开发中每次设置元素的大小都基于这个比例,那我们只需要关注屏幕宽度就可以了.换句话说,我们通过js去拿到屏幕宽度,然后去换算出每一份的值, 把这个值作为根节点的font-size
,不就解决问题了.
实际的是,浏览器字体最小是12px
, 如果100份,那换算出来只有个位数大小.浏览器不支持了,我们一般都换算10份.
这里还涉及一个概念,就是设备像素比(device pixel ratio)
,它是用物理像素/设备独立像素得到的
.在Javascript中可以通过window.devicePixelRatio
获取当前设备的dpr.我们可以通过dpr设置body的font-size来支持项目中的字体适配em这个单位.
css:
html {
font-size: 37.5px; /* 375/10 */
}
body {
font-size: 24px; /* 12 * dpr 修正字体大小 */
width: 10rem;
}
.p1 {
width: 5rem;
height: 5rem;
font-size: 1.2em; /* 字体使用em */
}
html:
...
<body>
<div class="p1">
<div class="s1"></div>
</div>
</body>
...
js:
var doc = document.documentElement;
function callback() {
var rem = docEl.clientWidth / 10
docEl.style.fontSize = rem + 'px'
if (document.body) {
// 设置全局body为当前dpr * 12px
document.body.style.fontSize = (12 * dpr) + 'px'
}
}
document.addEventListener('DOMContentLoaded', callback);
window.addEventListener('resize', callback)
上面的例子可以使用rem
做移动端优化,但是字体使用的是em
.原因就是设置根节点字体大小,会影响所以字体大小,字体大小会继承.总不能每个字体都设置字体大小...还有就是大屏用户可以选择要更大的字体还是更多的内容,如果使用rem,那就限制了用户的选择.所以在开发中,图片盒子宽度这些使用rem
, 字体大小使用em
.
vue项目如何使用
在vue项目中其实有比较成熟的方案了.lib-flexible
与Postcss(pxtorem)
.前者所做的事情就是去获取屏幕并换算出合适的根font-size
值,后者顾名思义,就是把px
转为rem
,方便我们在项目中可以放心使用px
这个单位开发.这里是源码位置:lib-flexible,Postcss(pxtorem)
使用起来很简单只需要:
npm i amfe-flexible --save-dev
npm i postcss postcss-pxtorem --save-dev
然后在项目中分别引入:
main.js
import "amfe-flexible";
vue.config.js
css: {
loaderOptions: {
postcss: {
plugins: [
require("postcss-pxtorem")({
rootValue: 37.5,
propList: ["*"], //作用于哪些标签
})
]
}
}
}
这样就可以了.至于amfe-flexible
与pxtorem
具体原理,可以去看源码.下面贴一部分amfe-flexible
的代码,其实很简单:
var docEl = document.documentElement
var dpr = window.devicePixelRatio || 1
// adjust body font size
function setBodyFontSize () {
if (document.body) {
// 设置全局body为当前dpr * 12px
document.body.style.fontSize = (12 * dpr) + 'px'
}
else {
document.addEventListener('DOMContentLoaded', setBodyFontSize)
}
}
setBodyFontSize();
// set 1rem = viewWidth / 10
function setRemUnit () {
var rem = docEl.clientWidth / 10
docEl.style.fontSize = rem + 'px'
}
setRemUnit()
// reset rem unit on page resize
window.addEventListener('resize', setRemUnit)
window.addEventListener('pageshow', function (e) {
if (e.persisted) {
setRemUnit()
}
})
if (dpr >= 2) {
var fakeBody = document.createElement('body')
var testElement = document.createElement('div')
testElement.style.border = '.5px solid transparent'
fakeBody.appendChild(testElement)
docEl.appendChild(fakeBody)
if (testElement.offsetHeight === 1) {
docEl.classList.add('hairlines')
}
docEl.removeChild(fakeBody)
}
对于setBodyFontSize
这个方法,官方的解释在这里.,个人觉得用来设置字体的单位em
倒是也可以.
pxtorem
作为一个plugin,可想而知它做的事情就是基于webpack而完成的,对代码解析,然后把项目开发时的px
转换为rem
.
总结
一个项目做完,总得有所收获.移动端适配也算是web开发的一个经典难题,从开始到解决这个过程也是挺艰辛的,而我们现在能站在巨人的肩膀上去做事,能做的就是了解这个历程,这样能让我们有很多收获与新的感悟.
尽管目前来说flexible
不更新维护了,这边的目的在于搞清楚它到底做了什么.毕竟现在浏览器对rem
是挺友好的.等后续vw/vh
可以完美支持了,可以修改方案.
加油.
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!