uniapp实现的H5字体跨平台优化-如何兼容小软件
文章目录
前言
1. 添加条件编译
文件: src/style/fonts.scss
使用 /* #ifndef MP */ 和 /* #endif */ 包裹 @font-face 定义,确保:
- H5 和 App 平台正常加载字体文件
- 小程序平台不会引入无效的
@font-face代码
/* #ifndef MP */
// H5 和 App 平台使用 @font-face
@font-face {
font-family: 'PingFang SC';
src: url('/static/fonts/PingFangRegular.ttf') format('truetype');
font-weight: 400;
}
/* #endif */
/* #ifdef MP */
// 小程序平台说明注释
/* #endif */
2. 完善字体栈
文件: src/App.vue
设置了完整的字体降级方案:
font-family: 'PingFang SC', -apple-system, BlinkMacSystemFont,
'Helvetica Neue', Arial, 'Microsoft YaHei', sans-serif;
3. 添加平台说明注释
在关键文件中添加了详细的平台兼容性说明:
src/style/fonts.scss- 字体定义文件src/App.vue- 全局样式src/uni.scss- SCSS 变量
4. 创建小程序字体加载工具
文件: src/utils/loadMiniProgramFonts.js
/**
* 小程序自定义字体加载工具
*
* 使用说明:
* 1. 将字体文件上传到 CDN(支持 HTTPS)
* 2. 在小程序后台配置 CDN 域名白名单
* 3. 在 App.vue 的 onLaunch 中调用此函数
*
* 注意事项:
* - 字体文件必须是网络地址(不能是本地文件)
* - 字体文件大小建议 < 2MB
* - 加载字体会增加首屏加载时间
* - 建议只在必要时使用(如品牌字体要求)
*/
/**
* 加载微信小程序字体
* @param {Object} options 配置选项
* @param {string} options.fontFamily 字体名称,默认 'PingFang SC'
* @param {string} options.fontUrl 字体文件 CDN 地址
* @param {Function} options.onSuccess 成功回调
* @param {Function} options.onFail 失败回调
*/
export function loadWechatFont(options = {}) {
// #ifdef MP-WEIXIN
const {
fontFamily = 'PingFang SC',
fontUrl = '',
onSuccess = () => {},
onFail = () => {}
} = options
if (!fontUrl) {
console.warn('[字体加载] 未提供字体 URL')
return
}
console.log(`[字体加载] 开始加载字体: ${fontFamily}`)
wx.loadFontFace({
family: fontFamily,
source: `url("${fontUrl}")`,
success: (res) => {
console.log(`[字体加载] 字体加载成功: ${fontFamily}`, res)
onSuccess(res)
},
fail: (err) => {
console.error(`[字体加载] 字体加载失败: ${fontFamily}`, err)
onFail(err)
}
})
// #endif
}
/**
* 加载支付宝小程序字体
* @param {Object} options 配置选项
*/
export function loadAlipayFont(options = {}) {
// #ifdef MP-ALIPAY
const {
fontFamily = 'PingFang SC',
fontUrl = '',
onSuccess = () => {},
onFail = () => {}
} = options
if (!fontUrl) {
console.warn('[字体加载] 未提供字体 URL')
return
}
console.log(`[字体加载] 开始加载字体: ${fontFamily}`)
my.loadFontFace({
family: fontFamily,
source: `url("${fontUrl}")`,
success: (res) => {
console.log(`[字体加载] 字体加载成功: ${fontFamily}`, res)
onSuccess(res)
},
fail: (err) => {
console.error(`[字体加载] 字体加载失败: ${fontFamily}`, err)
onFail(err)
}
})
// #endif
}
/**
* 加载多个字重的字体
* @param {Object} options 配置选项
* @param {string} options.fontFamily 字体名称
* @param {Array} options.fonts 字体配置数组 [{weight: 400, url: '...'}, ...]
*/
export function loadMultipleWeights(options = {}) {
const { fontFamily = 'PingFang SC', fonts = [] } = options
if (fonts.length === 0) {
console.warn('[字体加载] 未提供字体配置')
return
}
// #ifdef MP-WEIXIN
fonts.forEach(font => {
loadWechatFont({
fontFamily: `${fontFamily}-${font.weight}`,
fontUrl: font.url,
onSuccess: () => {
console.log(`[字体加载] ${fontFamily} ${font.weight} 加载成功`)
},
onFail: (err) => {
console.error(`[字体加载] ${fontFamily} ${font.weight} 加载失败`, err)
}
})
})
// #endif
// #ifdef MP-ALIPAY
fonts.forEach(font => {
loadAlipayFont({
fontFamily: `${fontFamily}-${font.weight}`,
fontUrl: font.url,
onSuccess: () => {
console.log(`[字体加载] ${fontFamily} ${font.weight} 加载成功`)
},
onFail: (err) => {
console.error(`[字体加载] ${fontFamily} ${font.weight} 加载失败`, err)
}
})
})
// #endif
}
/**
* 使用示例:
*
* // 在 App.vue 的 onLaunch 中调用
* import { loadWechatFont, loadMultipleWeights } from '@/utils/loadMiniProgramFonts'
*
* export default {
* onLaunch() {
* // 方式 1: 加载单个字体
* loadWechatFont({
* fontFamily: 'PingFang SC',
* fontUrl: 'https://your-cdn.com/fonts/PingFangRegular.ttf',
* onSuccess: () => {
* console.log('字体加载成功')
* }
* })
*
* // 方式 2: 加载多个字重
* loadMultipleWeights({
* fontFamily: 'PingFang SC',
* fonts: [
* { weight: 400, url: 'https://your-cdn.com/fonts/PingFangRegular.ttf' },
* { weight: 500, url: 'https://your-cdn.com/fonts/PingFangMedium.ttf' },
* { weight: 600, url: 'https://your-cdn.com/fonts/PingfangSemibold.ttf' }
* ]
* })
* }
* }
*/
提供了可选的小程序网络字体加载方案,包括:
loadWechatFont()- 微信小程序字体加载loadAlipayFont()- 支付宝小程序字体加载loadMultipleWeights()- 批量加载多个字重
5. 创建平台测试页面
文件: src/pages/font-platform-test.vue
提供了跨平台字体渲染测试页面,可以:
- 检测当前运行平台
- 显示平台字体支持情况
- 测试不同字重的渲染效果
- 显示预期表现说明
平台表现对比
| 平台 | @font-face | 字体加载 | 显示效果 | 性能影响 |
|---|---|---|---|---|
| H5 | ✅ 支持 | 加载自定义字体 | PingFang SC | 需要下载字体文件 |
| iOS App | ✅ 支持 | 使用系统字体 | PingFang SC | 无额外开销 |
| Android App | ✅ 支持 | 加载自定义字体 | PingFang SC | 需要打包字体文件 |
| 小程序 iOS | ❌ 不支持 | 使用系统字体 | PingFang SC | 无额外开销 |
| 小程序 Android | ❌ 不支持 | 使用系统字体 | Roboto/思源 | 无额外开销 |
使用建议
当前配置(推荐)
适用于大多数场景,无需额外配置:
// App.vue - 无需修改
export default {
onLaunch() {
// 不需要额外的字体加载代码
}
}
优点:
- ✅ H5 和 App 显示一致
- ✅ 小程序使用系统字体,性能最佳
- ✅ 无需额外配置
- ✅ 代码简洁
缺点:
- ⚠️ 小程序 Android 无法显示 PingFang SC
小程序网络字体方案(可选)
如果必须在小程序 Android 上显示 PingFang SC:
// App.vue
import { loadWechatFont } from '@/utils/loadMiniProgramFonts'
export default {
onLaunch() {
// #ifdef MP-WEIXIN
loadWechatFont({
fontFamily: 'PingFang SC',
fontUrl: 'https://your-cdn.com/fonts/PingFangRegular.ttf',
onSuccess: () => {
console.log('字体加载成功')
}
})
// #endif
}
}
前置条件:
- 将字体文件上传到 CDN(支持 HTTPS)
- 在小程序后台配置 CDN 域名白名单
- 字体文件大小 < 2MB
优点:
- ✅ 所有平台显示一致
缺点:
- ⚠️ 增加首屏加载时间
- ⚠️ 需要 CDN 和域名配置
- ⚠️ 字体文件大小限制
测试方法
1. H5 测试
# 启动 H5 开发服务器
npm run dev:h5
# 访问测试页面
http://localhost:8080/#/pages/font-platform-test
在浏览器开发者工具中:
- Network 面板查看字体文件加载
- Elements 面板查看元素的 Computed 样式
2. 小程序测试
# 微信小程序
npm run dev:mp-weixin
# 支付宝小程序
npm run dev:mp-alipay
在小程序开发者工具中:
- 使用 iOS 模拟器测试系统 PingFang SC
- 使用 Android 模拟器测试降级字体
3. App 测试
# iOS App
npm run dev:app-ios
# Android App
npm run dev:app-android
在真机或模拟器上测试字体渲染效果。
性能优化建议
1. 字体文件优化
如果字体文件过大,可以:
# 安装 fonttools
pip install fonttools brotli
# 提取常用字符子集
pyftsubset PingFangRegular.ttf \
--text-file=common-chars.txt \
--output-file=PingFangRegular-subset.ttf
2. 使用 WOFF2 格式(H5)
WOFF2 比 TTF 小 30-50%:
@font-face {
font-family: 'PingFang SC';
src: url('/static/fonts/PingFangRegular.woff2') format('woff2'),
url('/static/fonts/PingFangRegular.ttf') format('truetype');
font-weight: 400;
}
3. 按需加载字重
只加载常用的 3-4 个字重,而不是全部 5 个。
4. 字体预加载(H5)
在 index.html 中添加:
<link rel="preload"
href="/static/fonts/PingFangRegular.woff2"
as="font"
type="font/woff2"
crossorigin>
常见问题
Q1: 为什么 H5 没有加载字体文件?
可能原因:
- 页面上没有元素使用
font-family: 'PingFang SC' - 字体文件路径不正确
- 浏览器缓存问题
解决方法:
- 检查
App.vue中是否设置了全局字体 - 检查
fonts.scss中的路径 - 清除浏览器缓存后重试
Q2: 小程序 Android 能否显示 PingFang SC?
默认情况: 不能,会降级到系统默认字体。
解决方案: 使用网络字体加载(参考上文"小程序网络字体方案")。
Q3: iOS App 会加载字体文件吗?
不会。 iOS 系统自带 PingFang SC,浏览器会优先使用系统字体,不会下载字体文件。
Q4: 字体文件太大怎么办?
优化方案:
- 使用字体子集化(只包含常用字符)
- 使用 WOFF2 格式(H5)
- 只加载必要的字重(3-4 个)
- 考虑使用系统字体栈
相关文档
自定义字体跨平台指南
平台兼容性分析
当前实现的平台表现
| 平台 | @font-face 支持 | PingFang SC 系统字体 | 实际效果 |
|---|---|---|---|
| H5 | ✅ 完全支持 | ❌ 无 | 加载自定义字体文件 |
| iOS App | ✅ 支持 | ✅ 系统自带 | 优先使用系统字体 |
| Android App | ✅ 支持 | ❌ 无 | 加载自定义字体文件 |
| 微信小程序 | ❌ 不支持 | iOS: ✅ / Android: ❌ | iOS 用系统字体,Android 用默认字体 |
| 支付宝小程序 | ❌ 不支持 | iOS: ✅ / Android: ❌ | iOS 用系统字体,Android 用默认字体 |
问题说明
1. 小程序平台的限制
微信小程序不支持 @font-face,但提供了 wx.loadFontFace() API:
// 微信小程序中加载网络字体
wx.loadFontFace({
family: 'PingFang SC',
source: 'url("https://your-cdn.com/fonts/PingFangRegular.ttf")',
success: console.log,
fail: console.error
})
限制:
- 字体文件必须是网络地址(不能是本地文件)
- 需要配置域名白名单
- 字体文件大小有限制(建议 < 2MB)
2. Android 系统没有 PingFang SC
Android 系统默认字体是 Roboto 或 思源黑体,没有 PingFang SC。如果要在 Android 上显示 PingFang,必须:
- 打包字体文件到 App
- 或通过网络加载字体
3. iOS 系统自带 PingFang SC
iOS 9+ 系统自带 PingFang SC,直接使用 font-family: 'PingFang SC' 即可,不需要加载字体文件。
推荐方案
方案 1:条件编译 + 平台适配(推荐)
针对不同平台使用不同的字体策略:
/* src/style/fonts.scss */
/* H5 和 App 平台使用 @font-face */
// #ifndef MP
@font-face {
font-family: 'PingFang SC';
src: url('/static/fonts/PingFangRegular.ttf') format('truetype');
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'PingFang SC';
src: url('/static/fonts/PingFangMedium.ttf') format('truetype');
font-weight: 500;
font-style: normal;
font-display: swap;
}
// 其他字重...
// #endif
/* 小程序平台使用系统字体 */
// #ifdef MP
/* 小程序不支持 @font-face,iOS 使用系统 PingFang,Android 使用默认字体 */
// #endif
App.vue 中的全局样式:
/* 全局字体设置 - 跨平台兼容 */
page,
view,
text,
button,
input,
textarea {
/* iOS: 使用系统 PingFang SC */
/* Android: 使用自定义 PingFang SC(如果加载成功)或 Roboto */
/* 小程序: iOS 用 PingFang SC,Android 用默认字体 */
font-family: 'PingFang SC', -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Roboto', 'Noto Sans SC', 'Microsoft YaHei', sans-serif;
}
方案 2:使用网络字体(适合小程序)
如果需要在小程序中使用自定义字体:
// App.vue - onLaunch
export default {
onLaunch() {
// #ifdef MP-WEIXIN
// 微信小程序加载网络字体
wx.loadFontFace({
family: 'PingFang SC',
source: 'url("https://your-cdn.com/fonts/PingFangRegular.ttf")',
success: () => {
console.log('字体加载成功')
},
fail: (err) => {
console.error('字体加载失败', err)
}
})
// #endif
// #ifdef MP-ALIPAY
// 支付宝小程序类似
my.loadFontFace({
family: 'PingFang SC',
source: 'url("https://your-cdn.com/fonts/PingFangRegular.ttf")',
success: () => {
console.log('字体加载成功')
},
fail: (err) => {
console.error('字体加载失败', err)
}
})
// #endif
}
}
注意事项:
- 字体文件需要上传到 CDN
- 需要在小程序后台配置域名白名单
- 字体文件会增加首屏加载时间
方案 3:使用相似的系统字体(最简单)
不使用自定义字体,而是使用各平台的优质系统字体:
/* 使用系统字体栈 */
page,
view,
text {
font-family:
-apple-system, /* iOS/macOS 系统字体(包括 PingFang SC) */
BlinkMacSystemFont, /* macOS Chrome */
'Segoe UI', /* Windows */
'Roboto', /* Android */
'Noto Sans SC', /* Android 中文 */
'Helvetica Neue', /* 旧版 iOS */
'Microsoft YaHei', /* Windows 中文 */
sans-serif; /* 后备字体 */
}
优点:
- 无需加载字体文件,性能最佳
- 跨平台兼容性好
- 用户体验一致(使用系统原生字体)
缺点:
- 不同平台显示的字体不完全一致
- 无法精确控制字体样式
实际测试建议
测试清单
H5 浏览器
- Chrome DevTools 网络面板查看字体加载
- 检查字体渲染效果
iOS 真机/模拟器
- 检查是否使用系统 PingFang SC
- 测试不同字重显示
Android 真机/模拟器
- 检查自定义字体是否加载成功
- 测试字体文件大小对性能的影响
微信小程序
- iOS 设备:检查系统 PingFang 显示
- Android 设备:检查降级字体显示
其他小程序平台
- 支付宝、抖音、百度等
性能优化建议
1. 字体文件优化
# 使用 fonttools 压缩字体文件
pip install fonttools brotli
# 提取常用字符子集(减小文件大小)
pyftsubset PingFangRegular.ttf \
--text-file=common-chars.txt \
--output-file=PingFangRegular-subset.ttf \
--flavor=woff2
2. 使用 WOFF2 格式(H5)
WOFF2 比 TTF 小 30-50%:
@font-face {
font-family: 'PingFang SC';
src: url('/static/fonts/PingFangRegular.woff2') format('woff2'),
url('/static/fonts/PingFangRegular.ttf') format('truetype');
font-weight: 400;
font-display: swap;
}
3. 字体预加载(H5)
<!-- index.html -->
<link rel="preload"
href="/static/fonts/PingFangRegular.woff2"
as="font"
type="font/woff2"
crossorigin>
4. 按需加载字重
只加载常用的字重(400、500、600),避免加载所有字重:
/* 只加载 3 个常用字重 */
@font-face {
font-family: 'PingFang SC';
src: url('/static/fonts/PingFangRegular.ttf') format('truetype');
font-weight: 400;
}
@font-face {
font-family: 'PingFang SC';
src: url('/static/fonts/PingFangMedium.ttf') format('truetype');
font-weight: 500;
}
@font-face {
font-family: 'PingFang SC';
src: url('/static/fonts/PingfangSemibold.ttf') format('truetype');
font-weight: 600;
}
总结
当前的跨平台优化方案:
✅ 已完成:
- 条件编译优化(小程序不加载无效代码)
- 完整的字体降级方案
- 详细的平台说明文档
- 可选的小程序网络字体加载工具
- 平台测试页面
✅ 推荐配置:
- 保持当前实现(无需额外配置)
- H5 和 App 使用自定义字体
- 小程序使用系统字体
✅ 性能表现:
- H5: 需要下载字体文件(一次性)
- iOS App: 无额外开销
- Android App: 字体文件打包到 App
- 小程序: 无额外开销
这个方案在保证视觉一致性的同时,兼顾了性能和开发成本。

浙公网安备 33010602011771号