Write By CS逍遥剑仙
我的主页: csxiaoyao.com
GitHub: github.com/csxiaoyaojianxian
Email: sunjianfeng@csxiaoyao.com QQ: 1724338257
最常用的 绝对单位,按精确像素计算
em
是 相对单位,基准为父节点字体大小,若自身定义了 font-size
则按自身计算,不推荐使用rem
是 相对单位,css3新加,按照根节点 <html>
的字号作为基准,下方提供的设置根节点 62.5% 的方案并不推荐,具体实践见第二节的介绍/* 根节点字体大小设置为 62.5%,即 10px 可以方便计算,否则将以浏览器默认字号 16px 为基准 */
/* 10 ÷ 16 × 100% = 62.5% */
/* 但 chrome 最小的字体大小为 12px,因此浏览器中的字体均 >= 1.2rem */
html { font-size: 62.5%; }
body { font-size: 1.4rem; } /* 1.4 × 10px = 14px */
vw
/ vh
即 viewpoint width / height,按照 视窗 的宽高的百分比进行计算,和 css 中的 %
按照父元素的宽高作为计算基准的方式不同vmin
/ vmax
取视窗宽高二者中较小 / 大值的百分比进行计算/* 元素始终在屏幕上可见 */
.box {
width: 100vmin;
height: 100vmin;
}
/* 元素始终铺满整屏 */
.box {
width: 100vmax;
height: 100vmax;
}
%
百分比,一般相对于父元素,但对于 position: absolute;
的元素是相对于已定位的父元素,对于 position: fixed;
的元素是相对于可视窗口,并且当父元素没有指定高度时,子元素设置百分比没有效果,高度直接为子元素的实际高度vm
css3 新单位,相对于视窗宽高较小的那个的百分比,兼容性较差下面的单位几乎用不到:
in
寸cm
厘米mm
毫米pt
point,约1/72寸pc
pica,大约6pt,1/6寸ch
...ex
......
移动端适配最简单的是通过js动态计算 viewport 的缩放值,但过于粗暴,会导致页面图片文字失真模糊。目前,移动端页面一般使用 rem
或 vw
/ vh
开发会较为方便,下面以 rem
为例:
为了方便计算,约定:100px = 1rem
,若设计师给到一张宽度为 750px 的设计稿,那么可以设置 html 的字体大小为 设备宽度 / 设计稿宽度 * 100
个px像素,以 iPhone 6/7/8 的宽度 375px 为例,则 html 字体的大小为 50px,即在宽度为 375 px 的设备上,1rem = 50px
。对于开发人员,一个宽度为 50px 的 div,就可以很轻松的通过除以 100,计算出对应的 rem 为 0.5rem,不需要再根据各种机型进行适配,0.5rem 换算到 iPhone 6/7/8 为 25px,而放到 750px 宽的设备上对应的是 50px。
总体来说,使用 rem 进行适配需要以下四步:
<meta name="viewport" content="initial-scale=1,maximum-scale=1,minimum-scale=1">
var clientWidth = document.documentElement.clientWidth
document.documentElement.style.fontSize = 100 * clientWidth / 750 + 'px'
建议设置监听,在页面尺寸变化时仍能正常展示
if (!document.addEventListener || !window.addEventListener) return
document.addEventListener('DOMContentLoaded', setScale, false)
window.addEventListener('orientationchange' in win ? 'orientationchange' : 'resize', setScale, false)
window.addEventListener('load', setScale, false)
上面第二部分通过动态设置 html 的 font-size 已经实现了页面随设计稿比例缩放,这种方式是页面宽度 100% 撑满设备宽度的,但是很多情况下,我们更希望部分横版页面能够高度撑满设备高度,而左右部分留白,此时有两种方式可以实现:
var clientHeight = document.documentElement.clientHeight
document.documentElement.style.fontSize = 100 * clientHeight / 375 + 'px'
var maxWidth = 670
var calWidth = Math.min(document.documentElement.clientWidth, maxWidth)
document.documentElement.style.fontSize = 100 * calWidth / 750 + 'px'
微信等 App 内可以设置默认字号,若用户修改了默认文字大小,会给上述的适配造成困扰,解决方法是先获取 App 的原始缩放比例,再在此基础上计算 font-size,实现如下:
// 创建1rem宽度的不可见元素,用于计算原始缩放比例
var scaleDom = (function () {
var scaleDom = document.createElement('div')
scaleDom.style.cssText = 'width:1rem;height:0;overflow:hidden;position:absolute;z-index:-2;visibility:hidden;'
document.body.appendChild(scaleDom)
return scaleDom
})()
// 计算使用过fontSize缩放(如微信)下的原始缩放比例
function getOriginScale () {
var htmlFontSize = Number(String(document.querySelector('html').style.fontSize || 16).replace('px', ''))
var instanceWidth = Number(String(window.getComputedStyle ? window.getComputedStyle(scaleDom).width : scaleDom.offsetWidth).replace('px', ''))
var scale = (htmlFontSize && instanceWidth) ? htmlFontSize / instanceWidth : 1
return scale
}
// 设置 html 用于处理 rem 的 font-size
function setScale () {
var scale = getOriginScale()
var clientWidth = document.documentElement.clientWidth
if (!clientWidth) return
window.uimakerScale = clientWidth / designWidth * scale
document.documentElement.style.fontSize = 100 * window.uimakerScale + 'px'
}
针对上述的适配方案,本文提供一套已在 html 自助化系统的生产环境中使用的适配代码作为最佳实践。
首先是 html 代码中需要配置视窗参数:
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
...
</head>
<body data-page-type="{{jsonData.pageType}}" data-design-width="{{jsonData.width}}" data-max-width="{{jsonData.maxWidth}}">
...
</body>
</html>
在初始化代码中执行下面的自执行函数,即可完成适配。
;(function (doc, win) {
// 页面数据
var pageType = parseInt(doc.body.getAttribute('data-page-type')) || 0 // 页面方向 0竖1横
var designWidth = parseInt(doc.body.getAttribute('data-design-width')) || 750 // 设计宽度
var maxWidth = parseInt(doc.body.getAttribute('data-max-width')) || designWidth // 最大页面适配宽度
// 创建1rem宽度的不可见元素,用于计算原始缩放比例
var scaleDom = (function () {
var scaleDom = doc.createElement('div')
scaleDom.style.cssText = 'width:1rem;height:0;overflow:hidden;position:absolute;z-index:-2;visibility:hidden;'
doc.body.appendChild(scaleDom)
return scaleDom
})()
// 计算使用过fontSize缩放(如微信)下的原始缩放比例
function getOriginScale () {
var htmlFontSize = Number(String(doc.querySelector('html').style.fontSize || 16).replace('px', ''))
var instanceWidth = Number(String(win.getComputedStyle ? win.getComputedStyle(scaleDom).width : scaleDom.offsetWidth).replace('px', ''))
var scale = (htmlFontSize && instanceWidth) ? htmlFontSize / instanceWidth : 1
return scale
}
// 设置 html 用于处理 rem 的 font-size 和 页面二次缩放
function setScale () {
var scale = getOriginScale()
var clientWidth = doc.documentElement.clientWidth
var clientHeight = doc.documentElement.clientHeight
if (!clientWidth || !clientHeight) return
var calWidth = maxWidth > 0 ? Math.min(clientWidth, maxWidth) : clientWidth
win.uimakerScale = calWidth / designWidth * scale
doc.documentElement.style.fontSize = 100 * win.uimakerScale + 'px'
}
setScale()
setTimeout(() => { setScale() }, 300)
if (!doc.addEventListener || !win.addEventListener) return
doc.addEventListener('DOMContentLoaded', setScale, false)
win.addEventListener('orientationchange' in win ? 'orientationchange' : 'resize', setScale, false)
win.addEventListener('load', setScale, false)
})(document, window)
移动端的适配已是老生常谈,市面上也有不少成熟的第三方库,但或多或少需要进行额外的配置,本文的方案是结合本人在一个自助化生成网页的项目的生产环境的实践中总结得出,若有更好的方案和建议欢迎和我交流。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。