uni-app x CSS font-size 全解析:跨端字体大小设置、单位选择与性能优化指南
2026/9/19 20:10:57 网站建设 项目流程

uni-app x CSS font-size 全解析:跨端字体大小设置、单位选择与性能优化指南

【免费下载链接】uni-appA cross-platform framework using Vue.js项目地址: https://gitcode.com/gh_mirrors/un/uni-app

导读

本文以 uni-app x 的font-size样式属性为线索,完整梳理该属性的语法、取值、兼容性与平台差异,并结合本仓库中的真实示例页与自动化测试源码,深入讲解 App 平台与 Web 平台在字体单位上的不同处理规则、rpx 在字号场景下的性能与精度问题,以及"样式不继承"带来的实践影响。读完本文,你将掌握在 uni-app x 中正确设置字体大小、合理选择 px 与 rpx、规避跨端兼容陷阱的完整实战方案。

font-size 属性定义

font-size属性用于设置字体大小。除直接改变文字显示尺寸外,它还有一个容易被忽略的连带作用:更改字体大小会更新字体大小相关的<length>单位值,例如line-height属性中em单位所引用的基准值——这一点在 Web 规范中表现明显,而在 App 平台由于单位支持范围受限(详见下文 App 平台差异),影响范围相对可控。

在 uni-app x 中,font-size属于text组件最核心的文本样式之一。由于 App 平台样式不继承,字号的设置位置直接决定其是否生效,这一点与 Web 端习惯存在显著差异,也是开发中出错的高频点。

uni-app x 兼容性

平台版本支持

| Web | Android | iOS | HarmonyOS | | :- | :- | :- | :- | | 4.0 | 3.9 | 4.11 | 4.61 |

App 平台拍平(flatten)兼容性

在蒸汽模式(Vapor)渲染引擎下,组件支持flatten拍平特性,font-size在拍平场景下的支持版本如下:

| Android(Vapor) | iOS(Vapor) | HarmonyOS(Vapor) | | :- | :- | :- | | 5.21 | 5.11 | 5.0 |

关于蒸汽模式(去掉虚拟 DOM 的 Vue 新功能)与拍平机制的背景,可参阅 蒸汽模式说明。简单理解,拍平(flatten)是把组件直接拍平到原生渲染管线中渲染,减少组件层级、提升渲染性能,而font-size在拍平路径下同样完整可用。

语法

font-size: <absolute-size> | <relative-size> | <length-percentage>;

值限制

  • length:即长度值。在 uni-app x 中,App 平台实际仅支持以 px 与 rpx 为单位的长度值(详见下文)。

font-size 的属性值

绝对大小关键字与相对大小关键字

| 名称 | 兼容性 | 描述 | | :- | :- | :- | | large | Web: 4.0; Android 系统版本: -; Android: -; iOS 系统版本: -; iOS: -; HarmonyOS 系统版本: -; HarmonyOS: - | 基于用户默认字体大小(medium)的绝对大小关键字。 | | larger | Web: 4.0; Android 系统版本: -; Android: -; iOS 系统版本: -; iOS: -; HarmonyOS 系统版本: -; HarmonyOS: - | 相对大小关键字。字体大小将相对于父元素的字体大小变大或变小,大致按照用于区分绝对大小关键字的比率。 | | medium | Web: 4.0; Android 系统版本: -; Android: -; iOS 系统版本: -; iOS: -; HarmonyOS 系统版本: -; HarmonyOS: - | 基于用户默认字体大小(medium)的绝对大小关键字。 | | small | Web: 4.0; Android 系统版本: -; Android: -; iOS 系统版本: -; iOS: -; HarmonyOS 系统版本: -; HarmonyOS: - | 基于用户默认字体大小(medium)的绝对大小关键字。 | | smaller | Web: 4.0; Android 系统版本: -; Android: -; iOS 系统版本: -; iOS: -; HarmonyOS 系统版本: -; HarmonyOS: - | 相对大小关键字。字体大小将相对于父元素的字体大小变大或变小,大致按照用于区分绝对大小关键字的比率。 | | x-large | Web: 4.0; Android 系统版本: -; Android: -; iOS 系统版本: -; iOS: -; HarmonyOS 系统版本: -; HarmonyOS: - | 基于用户默认字体大小(medium)的绝对大小关键字。 | | x-small | Web: 4.0; Android 系统版本: -; Android: -; iOS 系统版本: -; iOS: -; HarmonyOS 系统版本: -; HarmonyOS: - | 基于用户默认字体大小(medium)的绝对大小关键字。 | | xx-large | Web: 4.0; Android 系统版本: -; Android: -; iOS 系统版本: -; iOS: -; HarmonyOS 系统版本: -; HarmonyOS: - | 基于用户默认字体大小(medium)的绝对大小关键字。 | | xx-small | Web: 4.0; Android 系统版本: -; Android: -; iOS 系统版本: -; iOS: -; HarmonyOS 系统版本: -; HarmonyOS: - | 基于用户默认字体大小(medium)的绝对大小关键字。 | | xxx-large | Web: 4.0; Android 系统版本: -; Android: -; iOS 系统版本: -; iOS: -; HarmonyOS 系统版本: -; HarmonyOS: - | 基于用户默认字体大小(medium)的绝对大小关键字。 | | math | Web: 4.0; Android 系统版本: -; Android: -; iOS 系统版本: -; iOS: -; HarmonyOS 系统版本: -; HarmonyOS: - | 使用特殊的数学缩放规则来确定 font-size 属性的计算值。 |

关键结论:上表全部关键字(smallmediumlargelargersmallermath等)的兼容性列均标记为仅 Web 支持,App 平台不支持基于用户默认字体大小的绝对大小关键字,也不支持相对大小关键字。跨端开发时,不应在 App 端依赖这些关键字控制字号。

默认值

| 平台 | 默认值 | | :- | :- | | uvue | 16px |

注意:W3C 规范中的默认值为medium。而在 uni-app x 的 uvue 页面中,默认字号被确定为 16px,与大多数操作系统与浏览器的默认字号一致。也就是说,不显式设置font-size时,text组件渲染出的文字即为系统默认的 16px。

适用组件

font-size可作用于以下组件:

  • text
  • button
  • input
  • textarea

其中text是承载纯文本的核心组件。在 app-uvue 与 app-nvue 中,文本只能写在text组件内,文本样式也应写在text组件上,而不能写在父级view的样式中(详见 text 组件文档 与 样式不继承说明)。

App 平台差异

字体单位说明

App 平台(Android / iOS / HarmonyOS)对font-size的单位支持存在明确的边界:

  • 仅支持 px 和 rpx 单位,默认值为 16px。
  • 如果仅开发 App,属性值可以不设置单位,不设置单位时当作 px 处理。但这样无法兼容 Web 和小程序平台。
  • 不支持百分比单位、不支持基于用户默认字体大小的绝对大小关键字(如smallmediumlarge等)、不支持emremex等单位。
  • 虽然支持 rpx 但不推荐使用

默认字号与最佳实践

  • 正常情况下,普通字体不需要、也不应该设置font-size,使用默认的 16px 即可。
  • 更不需要显式书写font-size: 16px,这种多余的代码浪费性能。
  • 需要变大或变小的字体,基于 16px 的默认值适当增加或缩小字号即可。

为什么不在 font-size 中使用 rpx

在 font-size 中使用 rpx,类似于在 Web 开发中给字体大小设置百分比,缺乏实际意义,并且会引入三类具体问题:

  1. 超宽屏上字号脱离预期:rpx 根据屏幕宽度动态计算,在超宽屏(pad、折叠屏、横屏、PC 宽屏)上会显得异常地大。
  2. 性能损耗:rpx 性能不如 px,排版引擎需要根据屏幕宽度为页面中每个 text 设置样式。如果 text 组件很多(尤其是开发者给所有 text 都设置 rpx),会显著加重计算耗时。大部分字体应该不仅不用 rpx,甚至连 px 也不必显式设置,直接使用默认字号即可。
  3. 精度误差:rpx 会计算出小数,小数又需要取整,在不同情况下会产生精度误差。这在贴边场景下比较明显:有的屏幕上两个元素看起来是挨着的,有的屏幕上两个元素中间会出现一条缝。

更完整的单位取舍逻辑(性能 px > rpx > 百分比、px 是逻辑像素而非物理像素、不同单位在不同屏幕下的表现差异)可参考 长度单位说明。该文档同时给出了面向设计师的规范建议:按 1x 画布、390px 出普通竖屏图、834px 或 1280px 出宽屏图,并约束字号、间距、圆角等为固定枚举值,避免设计图随意给出无限种字号。

继承说明

App 平台不支持样式继承font-size也不例外。font-size仅对作用到的当前 text 组件生效,父级view上设置的字体样式不会传递给内部文字。

这与 Web 平台形成鲜明对比。在 Web 中文字样式会沿 DOM 树向下继承,但在 app-uvue 中,写在view的 text 区域的文字虽然会被编译器自动包裹一层text组件"看起来可用",实际却无法修改该文字的样式。因此正确做法是:文本一律放入text组件,字号样式一律写在text组件自身的 style 上。样式不继承的整体规则与排错建议详见 样式不继承 章节。由于 App 平台样式不继承,Web 中与继承相关的关键字inheritunset在 App 中也不支持。

Web 规范

  • 属性值必须设置单位,无单位时当作非法值处理。
  • 非法值会回退为默认值,即 16px。

这与 App 平台"无单位按 px 处理"的宽松策略不同。因此,若要保证同一套代码跨 App / Web / 小程序多端运行,务必为font-size显式写出单位,推荐统一使用px

实战示例:动态设置与读取 font-size

uni-app x 的官方示例(hello uni-app x)在pages/CSS/text/font-size.uvue中演示了font-size的完整玩法。本仓库的源码示例位于 src/pages/CSS/text/font-size.uvue,同时配套自动化测试 src/pages/CSS/text/font-size.test.js。

示例的核心要点:

  • 左侧为普通版本,右侧为flatten拍平版本,用于对比两种渲染路径下font-size的表现是否一致;
  • 通过setProperty('font-size', value)动态设置字号,并通过getPropertyValue('font-size')读取实际生效值;
  • 使用nextTick确保样式应用后再取值;
  • 通过枚举值与输入框覆盖空字符串、00px10px20px0rpx20rpx等边界取值,验证不同值的回退与换算行为。

核心代码片段如下:

<template> <!-- #ifdef APP && !VUE3-VAPOR --> <scroll-view style="flex: 1"> <!-- #endif --> <view style="flex-grow: 1;"> <text class="uni-tips">说明:左边是正常版本,右边是拍平版本</text> <view class="demo-box"> <view class="common"> <text ref="text" :style="{'font-size': data.fontSize}">font-size: {{data.fontSize}}</text> <text style="font-size: 30px;">font-size: 30px</text> <text style="font-size: 20rpx;">font-size: 20rpx</text> </view> <view class="common"> <text ref="text" :style="{'font-size': data.fontSize}" flatten>font-size: {{data.fontSize}}</text> <text style="font-size: 30px;" flatten>font-size: 30px</text> <text style="font-size: 20rpx;" flatten>font-size: 20rpx</text> </view> </view> <view class="uni-common-mt"> <text class="uni-title-text">setProperty 设置与 getPropertyValue 获取</text> </view> <view class="common-box"> <!-- 普通版本 --> <view class="uni-common-mt"> <text class="uni-title-text">font-size</text> <text class="uni-info">设置值: {{data.fontSizeProp}}</text> <text class="uni-info">获取值: {{data.fontSizeActual}}</text> <view class="test-box"> <text ref="textRef" :style="{ fontSize: data.fontSizeProp }">当前 font-size: {{data.fontSizeProp}}</text> </view> </view> <!-- 拍平版本 --> <view class="uni-common-mt"> <text class="uni-title-text">测试拍平</text> <text class="uni-info">设置值: {{data.fontSizeProp}}</text> <text class="uni-info">获取值: {{data.fontSizeActualFlat}}</text> <view class="test-box"> <text ref="textRefFlat" :style="{ fontSize: data.fontSizeProp }" flatten>当前 font-size: {{data.fontSizeProp}}</text> </view> </view> </view> <view class="uni-common-mt uni-common-mb"> <text class="uni-tips">第一个枚举值,'' (空字符串) - 空值情况</text> <enum-data :items="fontSizeEnum" title="font-size 枚举值" @change="radioChangeFontSize" :compact="true"></enum-data> <input-data :defaultValue="data.fontSizeProp" title="font-size 自定义值" type="text" @confirm="inputChangeFontSize"></input-data> </view> </view> <!-- #ifdef APP && !VUE3-VAPOR --> </scroll-view> <!-- #endif --> </template> <script setup lang="uts"> import { ItemType } from '@/components/enum-data/enum-data-types' const data = reactive({ fontSize: '15px', fontSizeProp: '15px', fontSizeActual: '', fontSizeActualFlat: '' }) // 自动化测试 const setFontSize = () => { data.fontSize = '30px' } const fontSizeEnum: ItemType[] = [ { value: 0, name: '' }, { value: 1, name: '0' }, { value: 2, name: '0px' }, { value: 3, name: '10px' }, { value: 4, name: '20px' }, { value: 5, name: '0rpx' }, { value: 6, name: '20rpx' }, ] const textRef = ref(null as UniTextElement | null) const textRefFlat = ref(null as UniTextElement | null) const getPropertyValues = () => { data.fontSizeActual = textRef.value?.style.getPropertyValue('font-size') ?? '' data.fontSizeActualFlat = textRefFlat.value?.style.getPropertyValue('font-size') ?? '' } const changeFontSize = (value: string) => { data.fontSizeProp = value textRef.value?.style.setProperty('font-size', value) textRefFlat.value?.style.setProperty('font-size', value) // 使用 nextTick 确保样式已应用后再获取值 nextTick(() => { getPropertyValues() }) } const radioChangeFontSize = (index: number) => { const selectedItem = fontSizeEnum.find((item): boolean => item.value === index) if (selectedItem != null) { changeFontSize(selectedItem.name) } } const inputChangeFontSize = (value: string) => { changeFontSize(value) } onReady(() => { getPropertyValues() }) defineExpose({ setFontSize, radioChangeFontSize, data }) </script>

对应的自动化测试 src/pages/CSS/text/font-size.test.js 通过page.callMethod("setFontSize")触发示例页暴露的setFontSize方法,将字号从15px切换到30px后截取全页截图并与快照比对,以此校验font-size在普通与拍平两种渲染路径下的渲染一致性:

describe('css-font-size', () => { let page; beforeAll(async () => { page = await program.reLaunch('/pages/CSS/text/font-size'); }); it('change font-size screenshot', async () => { await page.callMethod("setFontSize"); await page.waitFor(100); const image = await program.screenshot({ fullPage: true }); expect(image).toSaveImageSnapshot(); }); });

与其他文本属性的联动

font-size并非孤立属性,它与 line-height、font-weight、font-family 等共同构成文本排版体系。值得注意的是:

  • 在 Web 平台,line-heightem单位值以font-size为基准:子元素用自己的 font-size 乘以无单位数值,行高随字号自动适应(详见 line-height 文档);
  • 在 App 平台的 VDOM 模式下,em单位仅line-height属性支持,而font-size本身不支持em(见 字体大小单位表 与 line-height 文档);
  • 由于 App 平台样式不继承,字号必须直接写在text组件上,line-height 同理,需要在同一text组件内配套设置才能保证行距随字号正确缩放。

参见

  • text 组件文档
  • 长度单位说明(含 rpx 详解)
  • 样式不继承规则
  • 蒸汽模式(Vapor)说明
  • CSS 文档首页

【免费下载链接】uni-appA cross-platform framework using Vue.js项目地址: https://gitcode.com/gh_mirrors/un/uni-app

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询