最近做了一个大屏的项目,中间也遇到一些坑,结合自身和之前的项目总结记录一下关于适配的问题。
越来越多的项目都有涉及到数字大屏了,数据全部展示在首页显示,搭配各种各样的表格图就显得很有那味了,虽然大屏项目看着很高大,但是弄起来并不是好处理,首先要考虑的性能问题,能快速的展示数据和实时展示,再者就是布局的兼容性和适配能力,本篇暂时不讲数据性能先说大屏的适配开始。
移动端上的适配也是五花八门,其中说起来还要扯到屏幕的分辨率物理像素之类,原有也不讲那么多了,本篇只说思路和解决方案。
正文
大屏的适配方案和移动端还是略有不同的,因为大屏上的布局都是不可变,换句话来说,不管浏览器是怎么缩放大小,屏幕浏览器各个大小不一,里面的布局都是固定的排版大小,即使字体溢出,屏幕高度大小的不一,也要保持设计图布局不变,关键点是布局不可变;而移动端上的布局不会有那么多放大或缩小的考虑,一般都是固定的大小,根据屏幕的宽度变化也小,布局也不会变太多,其中高度是可以做到不固定的,或者不设置宽高。
针对 PC 大屏和移动端适配我们分开来讲。
大屏配
举例,一般设计图可能会给一个 1920 * 1080 的图大小,里面的设计模块都是区划好的排布,对不同的区块有不一样的大小,这里面的大小都要设置固定的宽高,这样才能在各个屏幕下的布局保持一致,但是有个问题就是每个屏幕的大小不一怎么做才能保持一致性呢?
这里就要说到布局的关键 CSS3 的属性 rem
了,通过 rem
来实现自适应适配。再说 rem
前先来了解一下其定义。
rem
是 CSS3 新增的一个相对单位(root em,根em)的缩写,rem作用于非根元素时,相对于根元素字体大小;rem作用于根元素字体大小时,相对于其出初始字体大小。
相对根 HTML 字体的 font-size
改变,默认的情况下是 任意浏览器的默认字体高都是16px 大小,这就表示所有的浏览器都支持是 1rem = 16px ,知道了两者换算关系之后我们就可以根据屏幕的大小来计算跟字体的大小了,对应的所有设置 rem
单位的大小都会改变。
对应的一个成熟的方案就是用淘宝的 fontjs 来动态改写根字体大小和另外一个 vw 布局。
font.js+rem 组合
这种的写法就 JS 动态监听浏览器的缩放,然后获取屏幕的宽度,再做计算,目的是为了设置其根字体为 1rem = 100px
,按设计图大小 1920 来算,刚好根字体为 100px, 这样计算的就很方便,对于要设置元素的宽高时,只要写 width: 100px
相当于 width: 1rem
。具体代码如下;
(function(doc, win) {
var docEl = doc.documentElement
var resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize'
var recalc = function() {
var clientWidth = docEl.clientWidth
if (!clientWidth) return
docEl.style.fontSize = 100 * (clientWidth / 1920) + 'px'
}
if (!doc.addEventListener) return
win.addEventListener(resizeEvt, recalc, false)
doc.addEventListener('DOMContentLoaded', recalc, false)
})(document, window)
不好就就是,这样的做会额外引入一个js,而且还要涉及到计算。可以借助插件 postcss-px-to-rem
包进行自动格式化转换。
module.exports = {
plugins: {
autoprefixer: {},
"@njleonzhang/postcss-px-to-rem": {
unitToConvert: 'px', // (String) 要转换的单位,默认是px。
widthOfDesignLayout: 1920, // (Number) 设计布局的宽度。对于pc仪表盘,一般是1920.
unitPrecision: 3, // (Number) 允许 REM 单位增长到的十进制数字.
selectorBlackList: ['.ignore', '.hairlines'], // (Array) 要忽略并保留为 px 的选择器.
minPixelValue: 1, // (Number) 设置要替换的最小像素值.
mediaQuery: false // (Boolean) 允许在媒体查询中转换 px.
}
}
}
vw 和 vh 配合
关于 vw (viewpoint width 视窗宽度)和 vh 的用法介绍
- 1屏幕视口宽度 = 100vw
- 1屏幕视口高度 = 100vh
所以按照设计图 1920 * 1080 的大小来计算
- 1920px = 100vw
- 1080px = 100vh
这样一来,以一个宽300px和200px的div来说,其作所占的宽高,以vw和vh为单位,计算方式如下:
vwDiv = (300px / 1920px ) * 100vw
vhDiv = (200px / 1080px ) * 100vh
得出一个其实际的元素 vw、wh宽高,但是这样会有一个问题,只对应1920 的分辨率才正常显示大小,如果是很大或者很小的屏幕是就表现的很大的文字,而且计算起来也不现实,每次的大小单位都要算一下就很麻烦了。
可以借助 scss
等预编译处理样式等,也可以用 postcss-px-to-viewport
差不多的包处理工具,就不在赘述了。
缺点也是很明显,需要手动计算和借助打包编译工具,比较麻烦。哪有没有不需要 JS 计算也不要打包配合实现的呢?答案肯定是有的。
vw 和 calc() 配合
上面说到了,一个屏幕的宽度就是 100vw 再加上 JS 获取的clientWidth
也是用来获取屏幕的宽度,这个不变,变的是计算的部分
- 第一个是用的 JS 计算得到根字体的大小
- 第二个是直接使用 100vw 加计算得出根字体大小
那不用这些我们可以使用 CSS3 提供的 calc() 来自动计算,具体操作如下;
- 使用css的 calc计算函数计算跟字体大小
- 对着设计图的宽度大小排版除以 100 ,比如说设计图是按 1920 * 1080的 那就是 19.2
- 使用100vw设置html 字体大小 (这里的100vw等同于一个屏幕的宽度)font-size: calc(100vw / 19.2)
- 然后可以在你需要设置字体的地方设置rem大小,比如标题大小在设计图上是18px 那么对应的rem就是 0.18rem,需要除以 100做换算,当然如果觉得麻烦可以借助编辑器插件自动帮你换算成rem即可。
这样的做法不仅可以省去引入js计算的麻烦,还可以方便的是用其换算进行适配操作,根据设计图的实际大小 px 计算出 rem 值。
缺点就是,涉及到的宽高都要进行计算,最好不使用百分比和 auto 都要精确到固定的值才能还原设计页面。
移动端适配
跟大屏适配的使用可以做一样的,使用 vw 加 calc() 结合,但只局限设置字体的大小,对元素的宽高来说也是要看设计布局来写 rem,不是盲目的都这样写,因为在移动端很少需要写固定的高度,对应的上面一条就需要固定宽高都要写到,而在移动端的自适应更多的是布局上的不是说固定不变,当然也要设置字体的大小适配,但是宽度和高度看情况给固定和百分比,常用的 CSS 布局可以用到 Flex
操作。
而且手机的屏幕大小多样性,不可能按照各样的手机做很多设计稿,最多就两种类型,一个是 iphone6 尺寸,另外一种就是 ipad 尺寸。这样的话如果写固定的宽度的话就需要两套样式代码了,所以在移动端的布局是,宽度看情况固定或者自适应大小,高度不设置大小撑开,特定除外。字体上也是差不多的,上面也说到了浏览器的默认根字体大小是 16px ,即 1rem = 16px ,如果直接设置 px 来定义的话,在各个浏览器的展示效果上会有所不同,但区别也不会太大,为了综合考虑可以统一设置字体的百分比 62.5% 。
举个栗子 ?
12px=0.75em,10px=0.625em。为了简化font-size的换算,需要在 css 中的 html 选择器中声明 font-size=62.5%
,这就使 rem 值变为 16px*62.5% = 10px, 这样 12px = 1.2em,10px = 1em,,也就是说只需要将你的原来的 px 数值除以10,然后换上 rem 作为单位就行了