REM 布局

动态计算 HTML 根节点字体大小 + postcss-plugin-px2rem 插件

  • 计算根节点字体大小

    public/index.html

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    <script>
    function calculateSize() {
    let clientWidth =
    document.documentElement.getBoundingClientRect().width ||
    document.documentElement.clientWidth
    // 750 = 设计稿最大宽度值(px)
    if (clientWidth >= 750) {
    clientWidth = 750
    }
    // 7.5 = 设计稿最大宽度值(px)/ postcss-plugin-px2rem 插件的 rootValue 值 => 750 / 100
    let htmlSize = clientWidth / 7.5
    document.documentElement.style.fontSize = htmlSize + 'px'
    console.log('触发页面重绘!!!')
    }
    function debounce(func, delay) {
    let timeout = null
    return function () {
    clearTimeout(timeout)
    timeout = setTimeout(() => {
    func.apply(this, arguments)
    }, delay)
    }
    }
    calculateSize()
    window.addEventListener('resize', debounce(calculateSize, 500))
    </script>
  • 安装 postcss-plugin-px2rem 插件

    1
    yarn add postcss-plugin-px2rem -D
  • 配置 postcss-plugin-px2rem 插件

    vue.config.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    module.exports = {
    css: {
    loaderOptions: {
    postcss: {
    plugins: [
    require('postcss-plugin-px2rem')({
    rootValue: 100, // 换算基数,默认 100。 对应计算根节点中的割分视口份数值。以此样式代码中可直接写 设计稿的 Web px 值
    // exclude: /(node_module)/, // 默认转换整个项目除了 index.html 外的所有文件内容中的 px。在不需要转换 UI 框架中的 px 时,须取消注释。
    minPixelValue: 2 //设置要替换的最小像素值 (2px 会被转 rem)。 默认 0
    })
    ]
    }
    }
    }
    }

WeChat 内部的“字体”大小功能,会影响使用 REM 布局的网页

WeChat App 内部的“字体”大小功能,会影响在 WeChat 内部打开的网页的 HTML 根节点字体大小,进而影响使用 REM 布局的网页。

哪怕你的网页是有通过动态计算来设置 HTML 根节点字体大小的,也会受 WeChat App 内部这个字体大小修改机制的影响。感觉是强制覆盖!

但幸好,有办法解决!

在你执行动态计算根节点字体大小前,执行下述代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function preventWeChatModifyFontSizeForAndroid() {
if (typeof WeixinJSBridge == 'object' && typeof WeixinJSBridge.invoke == 'function') {
handleFontSize()
} else {
document.addEventListener('WeixinJSBridgeReady', handleFontSize, false)
}
function handleFontSize() {
// 设置网页字体为默认大小
WeixinJSBridge.invoke('setFontSizeCallback', { fontSize: 0 })
// 重写设置网页字体大小的事件
WeixinJSBridge.on('menu:setfont', function () {
WeixinJSBridge.invoke('setFontSizeCallback', { fontSize: 0 })
})
}
}
preventWeChatModifyFontSizeForAndroid()

实测(20210318)有效!马上去更新生产环境!🙌

在 iOS 平台,设置 WeChat 内部字体大小,无此类影响。