# @rsbuild/plugin-rem
Rem 插件实现移动端页面的 rem 自适应布局,能够根据屏幕大小来动态调整字体大小,让网页在不同大小的屏幕上都能够自适应显示。 插件提供以下能力: - 集成 [postcss-pxtorem](https://npmjs.com/package/postcss-pxtorem),将 CSS 中的 `px` 单位转换为 `rem`。 - 在 HTML 模版中插入运行时代码,对根元素 fontSize 进行设置。 ## Usage 安装: ```bash npm add @rsbuild/plugin-rem -D ``` 在 `rsbuild.config.ts` 中注册: ```ts // rsbuild.config.ts import { pluginRem } from '@rsbuild/plugin-rem'; export default { plugins: [pluginRem()], }; ``` ## 选项 ### 默认选项 ```js const defaultOptions = { enableRuntime: true, rootFontSize: 50, screenWidth: 375, rootFontSize: 50, maxRootFontSize: 64, widthQueryKey: '', excludeEntries: [], supportLandscape: false, useRootFontSizeBeyondMax: false, pxtorem: { rootValue: 50, unitPrecision: 5, propList: ['*'], }, }; ``` ### enableRuntime - **类型:** `boolean` - **默认值:** `true` 是否自动生成 runtime 代码来动态计算根元素字体大小。 ### inlineRuntime - **类型:** `boolean` - **默认值:** `true` 是否将 runtime 代码内联到 HTML 文件中。如果设置为 `false`,运行时代码会被抽取为一个独立的 `convert-rem.[version].js` 文件,并输出到产物目录下。 ### rootFontSize - **类型:** `number` - **默认值:** `50` 根元素字体值。 ```js pluginRem({ rootFontSize: 30, }); ``` ### maxRootFontSize - **类型:** `number` - **默认值:** `64` 最大根元素字体值。 ### widthQueryKey - **类型:** `string` - **默认值:** `''` 根据 `widthQueryKey` 的值去 url query 中取 client width。 ### screenWidth - **类型:** `number` - **默认值:** `375` UI 设计图宽度。 ### excludeEntries - **类型:** `string[]` - **默认值:** `[]` 设置不注入 runtime 代码的页面入口,数组的 item 是页面入口的名称。通常需要配合 `pxtorem.exclude` 使用。 ```ts // rsbuild.config.ts import { pluginRem } from '@rsbuild/plugin-rem'; export default { source: { entry: { page1: './src/page1/index.tsx', page2: './src/page2/index.tsx', }, }, plugins: [ pluginRem({ excludeEntries: ['page2'], }), ], }; ``` ### supportLandscape - **类型:** `boolean` - **默认值:** `false` 横屏时使用 height 计算 rem。 ### useRootFontSizeBeyondMax - **类型:** `boolean` - **默认值:** `false` 超过 `maxRootFontSize` 时,是否使用 `rootFontSize`。 ### pxtorem - **类型:** `object` - **默认值:** - `rootValue`:默认与 `rootFontSize` 相同 - `unitPrecision`:`5`。精确位数 - `propList`:`['*']`。支持转换的 CSS 属性 用于自定义 [postcss-pxtorem](https://github.com/cuth/postcss-pxtorem#options) 插件的选项。 ```js pluginRem({ pxtorem: { propList: ['font-size'], }, }); ``` ## 使用指南 ### CSS 属性值转换 由于默认的 rootFontSize 为 50。开启 rem 转换后,会按照 1rem = 50px 的比例,对 CSS 样式做如下转换: ```css /* input */ h1 { margin: 0 0 16px; font-size: 32px; line-height: 1.2; letter-spacing: 1px; } /* output */ h1 { margin: 0 0 0.32rem; font-size: 0.64rem; line-height: 1.2; letter-spacing: 0.02rem; } ``` Rsbuild 默认会对所有 CSS 属性进行转换,如果希望仅对 font-size 属性进行转换,可通过设置 `pxtorem.propList` 实现。 ```ts pluginRem({ pxtorem: { propList: ['font-size'], }, }); ``` ### 如何实现一些 CSS 属性不被转换为 REM? [pxtorem.propList](https://github.com/cuth/postcss-pxtorem#options) 除了可以指定哪些属性需要被转换外,可以通过 `!` 方式指定哪些元素不被转换: ```ts pluginRem({ pxtorem: { propList: ['*', '!border-width'], // 不转换 border-width 属性 }, }); ``` 如果只希望一些个别 CSS 属性不被转换为 REM 时,也可参考如下写法: ```css /* `px` 转换为 `rem` */ .convert { font-size: 16px; // 转换为 1rem } /* `Px` 或 `PX` 会被 `postcss-pxtorem` 忽略,但是可以被浏览器正常识别 */ .ignore { border: 1px solid; // 忽略 border-width: 2px; // 忽略 } ``` 更多信息可参考 [postcss-pxtorem](https://github.com/cuth/postcss-pxtorem#a-message-about-ignoring-properties)。 ### 根元素字体大小计算 页面根元素的字体大小的计算公式为: ``` 根元素字体大小 = 当前客户端屏幕宽度 * 根元素字体值 / UI 设计图宽度 (即:pageRootFontSize = clientWidth * rootFontSize / screenWidth) ``` 以屏幕宽度为 390 的手机端浏览器为例,根元素字体值的默认值为 50, UI 设计图宽度为 375。 此时计算出的页面根元素的字体大小为 52 (`390 * 50 / 375`)。 此时 1 rem 为 52px,CSS 样式中的 32px(0.64 rem),实际页面效果为 33.28 px。 ```ts pluginRem({ rootFontSize: 50, screenWidth: 375, }); ``` ### 设置根元素字体最大值 在桌面浏览器端,根据计算公式得到的页面根元素字体值往往过大,当计算出的结果超出了默认的最大根元素字体值时,则采用当前设置的最大根元素字体值为当前根元素字体值。 以屏幕宽度为 1920 的桌面浏览器为例,此时计算出的根元素的字体大小为 349,超出了最大根元素字体值 64。则采用 64 为当前的根元素字体值。 ```ts pluginRem({ maxRootFontSize: 64, }); ``` ### 如何获取页面实际生效的 rootFontSize 值? 页面实际生效的 rootFontSize 会根据当前页面的情况动态计算。你可以通过打印 `document.documentElement.style.fontSize` 查看,也可通过 `window.ROOT_FONT_SIZE` 获取。 ### 如何指定页面实际生效的 rootFontSize 值? 默认情况下,页面实际生效的 rootFontSize 会根据当前页面的情况动态计算,如果希望指定页面实际生效的 rootFontSize,可关闭 `enableRuntime` 配置,并在[自定义 HTML 模版](/config/html/template) 中自行注入 `document.documentElement.style.fontSize = '64px'`。 ```ts export default { html: { template: './static/index.html', }, plugins: [ pluginRem({ enableRuntime: false, }), ], }; ``` ### 如何判断 REM 是否生效? 1. CSS:查看生成的 `.css` 文件中对应属性的值是否从 px 转换成 rem。 2. HTML:打开页面控制台查看 `document.documentElement.style.fontSize` 是否存在有效值。 ## License [MIT](./LICENSE).