HTML转AttributedString时如何正确保留上标sup样式
解决方案
你不需要手动遍历AttributedString的属性范围,也不需要引入第三方库,利用系统HTML解析器原生支持内联CSS的特性,在解析前给HTML拼接全局样式即可,所有标签样式会在解析阶段自动应用到对应文本范围,不会出现全量覆盖属性的问题。
问题原因
你当前在HTML解析完成后,给全量文本范围统一加15号系统字体的属性,会直接覆盖解析器自动生成的<sup>上标、<sub>下标签自带的小字号、基线偏移属性,最终导致上标和正文字号一致、行高被撑乱。
实现代码
直接修改formatAttributedString方法,移除解析后全量添加字体、段落属性的逻辑,改为在原始HTML前拼接全局CSS样式:
func formatAttributedString() -> NSMutableAttributedString? { // 拼接全局样式,指定正文和特殊标签的显示规则 let styledHTML = """ <style> body { font: -apple-system 15pt; line-height: 20pt; margin: 0; padding: 0; } sup { font-size: 10pt; vertical-align: super; line-height: 0; } sub { font-size: 10pt; vertical-align: sub; line-height: 0; } </style> \(self.html) """ let data = Data(styledHTML.utf8) guard let attributedString = try? NSMutableAttributedString( data: data, options: [ .documentType: NSAttributedString.DocumentType.html, .characterEncoding: String.Encoding.utf8.rawValue ], documentAttributes: nil ) else { return nil } return attributedString }
配置说明
font: -apple-system会自动匹配iOS原生系统字体,彻底解决默认显示Times New Roman字体的问题- 正文全局设置15pt字号、20pt行高,和你预期的App正文样式完全一致
- 单独给
<sup>、<sub>标签设置10pt小字号,vertical-align属性会自动触发解析器添加正确的基线偏移,还原原生上标/下标效果 - 给上标下标设置
line-height: 0,避免特殊标签撑大整行行高,保证所有正文行高统一为20pt - 如果你的HTML中还有
<strong>粗体、<em>斜体等其他标签,也可以直接在style块中添加对应选择器的样式规则,解析时会自动生效。
内容的提问来源于stack exchange,提问作者Joshua Maza
相关产品推荐
相关产品推荐

