news 2026/9/2 14:36:24

字符宽度问题详解:从CSS单位到动态测量与文本截断

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
字符宽度问题详解:从CSS单位到动态测量与文本截断

前端开发里最容易被低估的一个问题,就是“字符宽度”。width: 200px明明写好了,用户输入第三个汉字就被截断;表格里中文和英文混排,列宽怎么调都对不齐;后端用substring(0, 10)截标题,列表出现“半截字”,只剩一个箭头或者半个省略号。

这些现象的根源其实很统一:你把“字符宽度”理解成了字符个数、固定像素或者等宽网格,实际上它是由字体度量、排版语言和上下文共同决定的动态值。如果你只在 CSS 里改宽度、在代码里数长度,永远是在猜,而不是在控制。

这篇文章想把“字符宽度”讲透。我会先说明字符宽度的底层概念,再分类讲 CSS 定宽、JS 动态计算宽度、后端按显示宽度截断这三条实践路径,最后给一份可直接使用的排错清单和工程建议。无论你是写前端页面、做表格组件,还是处理文本截断的后端接口,读完都能找到对应的方案。

1. 这篇文章真正要解决的问题

先定义一下讨论范围。本文说的“字符宽度”,不是指letter-spacing那种字距微调,也不是指word-spacing,而是指一个字符在最终渲染结果中实际占据的横向空间。它干扰开发者的形式有三种。

第一种,CSS 定宽失效。你给输入框设置了width: 200px,但输入一个汉字和输入 5 个英文字母,占用的视觉宽度完全不同。200px 能装下 13 个英文小写字母,却只能装下 6 个汉字。这说明px这个单位并不天然等于“显示多少个字符”。

第二种,中英文混排无法对齐。表格里一列放“姓名”,一列放“Name”,列宽始终无法统一。因为汉字大多是全角字符,英文字母是半角字符,全角和半角的横向占位比例在不同字体下差异很大。

第三种,后端截断把文本切坏了。业务需求经常是“标题最多显示 10 个字符”,开发直接substring(0, 10)。但 Java 的length()、Python 的len()统计的是 Unicode 码点数量,不是“看起来多宽”。一个 emoji、一个中文标点、一个全角括号,在显示宽度上和英文字母完全不等价。

有一个概念需要一开始就纠正:字符宽度 = 字符个体宽度 × 字体比例,不只看字符个数。谁在控制这个“字体比例”?是字体度量。看完下一节,你就知道为什么同样一段文字,在 Arial 和 Consolas 里占的宽度不一样。

1.1 哪些人最应该读这篇文章

如果你正在做以下事情中的任何一件,这篇文章是为你写的:

  • 前端开发:做表单、表格、搜索框、列表,需要让元素宽度和字符数量对齐。
  • 组件库作者:封装InputTagTable等组件,需要处理溢出、省略号、自适应宽度。
  • 后端开发:写接口时做文本截断、列表标题截断、导出 Excel 时控制列宽。
  • 运维或桌面端开发者:写命令行工具、终端表格时需要对齐输出,这本质也是字符宽度问题。

1.2 本文的核心判断

我的核心判断是:处理字符宽度,优先级应该是“测量优先、单位次之、截断兜底”

能用ch单位表达“几个字符”的场景,就用ch;需要精确控制动态宽度时,用canvas.measureText或等价能力做测量;后端截断时,不能只按字符数切,要做显示宽度估算,并且给超长文本留回退。这样你不再需要对着像素猜宽度,而是真正知道一段文本在某个字体下到底有多宽。

2. 字符宽度基础:先搞懂字体度量

“字符宽度”这个概念不是 CSS 发明的,它来自字体排版。你页面上的每个字符,在字体文件里都有一组度量数据。

2.1 字符宽度不是“字符个数”

字体中,每个字符都有一个横向行进宽度(advance width),表示这个字符渲染后,绘制下一个字符时光标要前进多少距离。这是字符宽度的本质。

大写 W 在常见比例字体里宽度接近 1em;小写 i 只有 W 的 1/3;汉字“中”在浏览器默认字体中通常占 1em;半角逗号则可能只占 0.2em。所以“10 个字符”这个说法本身就有问题,除非你明确说“10 个等宽字符”。

2.2 等宽字体与比例字体:同一个 width 含义完全不同

字体按字符宽度是否一致,分为等宽字体和比例字体。

等宽字体每个字符占用的行进宽度相同,例如 Consolas、Courier New、中文场景下的部分 CJK 字体。等宽字体适合代码、命令行、表格对齐。

比例字体不同字符宽度不同,例如 Arial、Helvetica、微软雅黑。绝大多数系统默认 UI 字体是比例字体。

这就是为什么同样设置width: 200px,代码编辑器里能对齐,页面表格里对不齐——它们使用的字体类型不同。

2.3 全角与半角:中文排版的特殊问题

在中文排版语境下,还有一组概念:全角字符和半角字符。

全角字符通常占 1em,半角字符约占 0.5em 或更少。韩文、日文假名、中文标点、全角括号都属于全角;英文大小写、数字、半角标点属于半角。

但是要注意一个细节:“全角占 1em、半角占 0.5em”只是一个近似值。不同字体、不同字号下,半角英文字母的实际宽度并不严格等于 0.5em。在微软雅黑下,半角数字约占 0.55em;在 Arial 下,又不一样。所以严谨地说,全角/半角是排版方向上的近似分类,不是物理学上的精确规律。

概念含义举例是否固定宽度
等宽字体所有字符行军宽度一致Consolas、Courier New是全字体等宽
比例字体字符宽度随字形变化Arial、微软雅黑
全角字符宽度接近当前字号中文、中文标点约 1em
半角字符宽度约为字号一半或更少英文、数字约 0.5em

3. CSS 中设置字符宽度的几种方式

CSS 里设置宽度,可选单位很多:pxemremchex。真正和“字符宽度”强相关的是chem

3.1 px 与 width:固定像素不等于字符宽度

width: 200px是固定物理宽度,和字体没有任何关系。它不会因为你换了字体就自动变成“能容纳 N 个字符”。

如果你需要输入框能容纳固定数量的字符,不要把width写死成像素,否则在不同字体、不同字号下,实际容纳量完全不同。应该用ch,或在 JS 中动态测量后设置像素值。

3.2 em、rem、ch、ex 的区别与适用场景

先看这四个单位的对比:

单位相对对象典型用途
em当前元素的 font-size设置内边距、缩进、按钮尺寸
rem根元素的 font-size全局一致的缩放尺寸
ch当前字体中数字 0 的宽度按字符数量定宽
ex当前字体的小写 x 高度特殊排版场景

ch单位的设计初衷就是“一个字符的宽度”。在等宽字体下,1ch就是字体的行进宽度,width: 20ch差不多等于 20 个字符的宽度。但在比例字体中,ch只代表数字 0 的宽度,不代表每个字符都一样宽,所以它只能近似控制。

em适合做块级元素的整体尺寸。比如按钮内边距用0.5em 1em,会随字号变化,这是设计系统里的常见做法,但它不是“字符宽度”的控制手段。

3.3 用 ch 实现“按字符数量定宽”

如果你希望表单输入框“最多显示 8 个字符”,并且使用的是等宽字体,ch是最直接的工具。

/* 文件路径:style.css */ .input-code { width: 10ch; font-family: Consolas, "Courier New", monospace; box-sizing: border-box; padding: 0.25em 0.5em; }

对应 HTML:

<!-- 文件路径:index.html --> <label> 验证码 : <input class="input-code" maxlength="10" placeholder="请输入验证码"> </label>

这样设置后,输入框宽度基础就是 10 个字符,而不是 120px 等固定值。要注意box-sizing: border-box会让 width 包含 padding 和 border,实际内容区可能小于 10ch,所以如果严格要“正好容纳 10 个字符”,最好先把 padding 算清楚。

3.4 文本溢出与换行对宽度的影响

字符宽度的另一个常见场景是“文本放不下”。CSS 中处理这个问题的核心属性是overflow-wrapword-breaktext-overflow

/* 文件路径:style.css */ .ellipsis { max-width: 20ch; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }

text-overflow: ellipsis是控制显示省略号的关键,但它只能在块级容器且overflow: hidden; white-space: nowrap;同时存在时生效。

这里真正容易踩坑的地方是:max-width的单位。如果你用20ch,在等宽字体下是 20 个字符,但在比例字体下,小写 i 很窄、大写 W 很宽,最终显示效果完全不是 20 个普通字符。所以“用 ch 做 ellipsis 容器宽度”只适合等宽字体场景;否则,你要根据实际内容动态测量。

4. 中英文混排中的字符宽度陷阱

中英文混排是把“字符宽度”问题放大得最明显的场景。中文是方块字,宽度近似一致;英文是比例字,宽度差异很大。二者混排时,如果直接按固定宽度处理,就会出现各类对齐问题。

4.1 为什么 input 无法精确显示 N 个字符

假如你希望输入框能容纳“3 个中文 + 5 个数字”,设置width: 8ch会怎样?在默认 UI 字体下,ch基于数字 0 的宽度,但汉字“中”通常比数字 0 宽,所以真实结果可能是只装下 6 个字符就溢出。

如果你的需求是“固定容纳 N 个汉字”,更稳妥的方式是用em。因为汉字宽度接近 1em,width: 8em大约可以容纳 8 个汉字。但如果你要混排中文和英文,em也会失效,因为英文不是 1em。

所以结论是:复杂文本不要依赖单一 CSS 单位去模拟字符宽度,动态测量是更可靠的方式

4.2 表格纵向对齐的常见错误

表格中对齐有两种常见诉求:数字列右对齐、文本列按宽度截断。

数字列右对齐时,不要用固定width,应该让列宽取决于数字的最大位数,同时用font-variant-numeric: tabular-nums让数字变成等宽数字。否则,同样是 4 位数字,“1111”和“8888”宽度不同,会导致数字列视觉上参差不齐。

/* 文件路径:style.css */ .num-cell { font-variant-numeric: tabular-nums; text-align: right; }

tabular-nums让数字使用等宽数字字形,这是处理数字列对齐的最快方案。

文本列截断时,则要回到 3.4 节的 ellipsis 方案。表格列宽建议用比例(百分数)或用min-width+max-width结合,不要用固定ch,因为单元格内容中英文混合,ch无法表达真实宽度。

4.3 textarea、input 与中文数字混排的实际场景

如果是一个“商品编码 + 商品名称 + 数量”的列表,编码段是全角还是半角、数字是几位精度,都会直接影响列宽。实际工程里更推荐这样处理:

  • 数字、英文、中文分别设定不同的宽度标准。
  • 超长内容优先使用省略号而不是换行。
  • 需要精确对齐时,后端返回展示宽度或前端动态测量。

下面一节讲的就是动态测量如何落地。

5. 动态计算字符宽度:canvas.measureText 实践

CSS 单位适合静态、近似场景。当你要做“根据内容自动拉伸输入框宽度”“让标签文本宽度等于内容宽度”“省略号按真实像素截断”这类动态需求时,必须测量文本的渲染宽度。

浏览器为这个需求提供了一个底层 API:canvas.measureText()

5.1 为什么需要动态测量

假设有个“标签”组件,内容可以是中文、英文、数字混合,你需要让标签的背景宽度刚好容纳文字,并在超过容器宽度时显示省略号。用百分比或 ch 都无法准确计算,因为单词间的空隙、字符的宽度、字体的粗细都会影响结果。此时只能用真实渲染引擎计算。

canvas.measureText返回文本在当前字体配置下的像素宽度,这与浏览器实际渲染结果非常接近。

5.2 JavaScript 实现文本宽度测量

// 文件路径:textWidth.js function getTextWidth(text, font) { const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); ctx.font = font || getComputedStyle(document.body).font; const metrics = ctx.measureText(text); return metrics.width; } // 用法 const w = getTextWidth('测试中文ABC123', '14px "Microsoft YaHei", sans-serif'); console.log(w); // 单位是 CSS 像素

这段代码的要点:先创建一个 canvas 上下文,设置字体,然后调用measureText。要注意两点:

  1. 必须保证传入的font字符串与页面实际使用的字体一致,否则测出来是错的。
  2. measureText返回的对象还有actualBoundingBoxLeftactualBoundingBoxRight等字段,它们表示字符实际着色的边界,比width更精确,但width已经能满足绝大多数布局需求。

5.3 动态控制输入框宽度案例

一个典型需求是:输入框宽度随输入内容变化。比如邮件标签填写时,输入几个字符,框就跟着变宽,但不超过最大宽度。

// 文件路径:autoWidthInput.js function autoResizeInput(input, maxWidth) { const font = getComputedStyle(input).font; const width = getTextWidth(input.value || input.placeholder, font); const target = Math.min(Math.max(width + 20, 40), maxWidth); input.style.width = target + 'px'; } document.querySelectorAll('.auto-width-input').forEach((input) => { input.addEventListener('input', () => autoResizeInput(input, 320)); });

常见问题是:输入框的边框和 padding 会额外占宽度,所以要预留余量(示例中+ 20就是给 padding 和 border 的补偿)。如果出现抖动,可以改用requestAnimationFrame节流:

let rafId; input.addEventListener('input', () => { cancelAnimationFrame(rafId); rafId = requestAnimationFrame(() => autoResizeInput(input, 320)); });

如果运行后输入框依然出现内容溢出,第一步要检查getComputedStyle(input).font返回的字体是否与页面渲染字体一致。尤其是input默认字体和body字体不一致的情况很常见,这会直接导致测量偏差。

6. 表单与表格对齐中的字符宽度实战

表单和表格是前端开发里字符宽度问题的高发区,这里集中给出可直接套用的方案。

6.1 表单 label 对齐最佳方式

表单 label 需要左对齐、右对齐或者顶部对齐时,很多人直接设置固定 width。

更好的做法是:让 label 宽度能容纳最长文案,并加上一两个汉字的余量。由于中文几乎等宽,可以用em单位。

/* 文件路径:style.css */ .form-item { display: flex; align-items: center; margin-bottom: 12px; } .form-item .label { flex: 0 0 auto; min-width: 6em; /* 支持 4~5 个汉字左右 */ text-align: right; padding-right: 0.5em; }

这里min-width: 6em而不是width: 6em,关键在长 label 时可以自动扩展,短 label 时保持统一右对齐。这对“字符宽度”的应用是一个重要经验:宽度控制尽量用 min-width/max-width,而不要锁死 width,让内容有自然伸缩的空间。

6.2 表格列宽设计的字符宽度思路

表格列宽建议按内容类型分类:

内容类型宽度策略说明
数字列table-layout: fixed+tabular-nums数字宽度稳定,容易对齐
ID/编码等宽字体 +ch或固定百分比编码类似等宽文本
中文文本min-width+ ellipsis不要写死,要允许伸缩
超长描述剩余宽度 + ellipsis给最后一列分配剩余空间

这里真正容易踩坑的是:table-layout: fixed会让列宽完全由表格第一行决定,超出部分要么溢出要么裁剪;table-layout: auto又让浏览器根据内容自动计算宽度,可能会发生列宽跳动。如果你的表格要稳定对齐,建议展示层用 fixed,但列宽值用百分比或者 min-width 控制。

/* 文件路径:style.css */ .grid-table { table-layout: fixed; width: 100%; border-collapse: collapse; } .grid-table .col-id { width: 10ch; font-family: Consolas, monospace; } .grid-table .col-name { min-width: 8em; } .grid-table .col-desc { width: auto; }

col-descwidth: auto会占据剩余宽度,配合单元格内部 ellipsis,既能自适应,又不会把表格撑乱。

7. 后端字符串截断与显示宽度计算

前后端分离后,很多字符串截断逻辑由后端完成。但后端没有渲染引擎,无法直接测量像素宽度,所以最常见的错误就是直接用字符串长度截断。

7.1 String.length() 为什么不能直接用

Java 的String.length()按 UTF-16 码元计数。一个中文汉字是一个码元,一个 emoji 可能是两个码元,一个全角括号是一个码元,一个英文字母也是一个码元。按它截断,会出现两个问题:

  1. 把 emoji 从中间截断,产生乱码。
  2. 截断结果在显示上参差不齐:同样是 10 个码元,“十个中文汉字”和“十个英文字母”在屏幕上占用的宽度差一倍。

7.2 Java 按显示宽度取子串

后端处理中文文本截断,业务侧通常接受“半角算 1、全角算 2”的近似宽度。下面提供一个常用的 Java 实现,核心是遍历字符,累计显示宽度,到阈值后停止并输出省略号。

// 文件路径:TextWidthUtil.java public class TextWidthUtil { public static int displayWidth(String text) { if (text == null) { return 0; } int width = 0; for (int i = 0; i < text.length(); i++) { char c = text.charAt(i); if (c >= '\u1100' && (c <= '\u115F' || c == '\u2329' || c == '\u232A' || (c >= '\u2E80' && c <= '\uA4CF') || (c >= '\uAC00' && c <= '\uD7A3') || (c >= '\uF900' && c <= '\uFAFF') || (c >= '\uFE10' && c <= '\uFE19') || (c >= '\uFE30' && c <= '\uFE6F') || (c >= '\uFF00' && c <= '\uFF60') || (c >= '\uFFE0' && c <= '\uFFE6'))) { width += 2; } else { width += 1; } } return width; } public static String truncateByWidth(String text, int maxWidth) { if (text == null) { return ""; } int width = 0; StringBuilder sb = new StringBuilder(); for (int i = 0; i < text.length(); i++) { char c = text.charAt(i); int charWidth = displayWidth(String.valueOf(c)); if (width + charWidth > maxWidth) { sb.append("…"); break; } sb.append(c); width += charWidth; } return sb.toString(); } }

上面的代码用了String.valueOf(c)做了简单判断,日常够用。如果你要处理代理对(例如 emoji),就必须用codePointAt并按 codePoint 遍历,否则会把 emoji 拆开。更稳妥的方式是引入通用库或自己按 codePoint 处理。

// 文件路径:TextWidthUtilWithEmoji.java public static String truncateByDisplayWidthSafe(String text, int maxWidth) { if (text == null) { return ""; } int width = 0; StringBuilder sb = new StringBuilder(); int index = 0; while (index < text.length()) { int codePoint = text.codePointAt(index); int charWidth = isWideCodePoint(codePoint) ? 2 : 1; if (width + charWidth > maxWidth) { sb.append("…"); break; } sb.appendCodePoint(codePoint); width += charWidth; index += Character.charCount(codePoint); } return sb.toString(); } private static boolean isWideCodePoint(int codePoint) { return displayWidth(new String(Character.toChars(codePoint))) == 2; }

注意:这个实现同样基于近似规则,会占用较多字符。对于精确控制生产环境,建议用现成库,例如 ICU 的UCharacter.getIntPropertyValue或专门的 EastAsianWidth 属性判断。

7.3 Python 按显示宽度计算

Python 中同样可以按半角 1、全角 2 做计算。要处理 emoji 组合序列,建议用unicodedata和字符宽度属性做近似判断。

# 文件路径:text_width.py import unicodedata def display_width(char: str) -> int: # 将控制字符和组合字符视为 0 if unicodedata.combining(char): return 0 # East Asian Width 为 Wide 或 Fullwidth 的字符按 2 计算 eaw = unicodedata.east_asian_width(char) if eaw in ('W', 'F'): return 2 return 1 def truncate_by_width(text: str, max_width: int) -> str: width = 0 result = [] for char in text: w = display_width(char) if width + w > max_width: result.append('…') break result.append(char) width += w return ''.join(result) if __name__ == '__main__': s = "测试中文字符ABC" print(display_width(s[0])) # 2 print(truncate_by_width(s, 8)) # 例子

这里unicodedata.east_asian_width是判断中文字符宽度的标准方法。实际生产环境中如果只处理普通文本,这套逻辑足够;如果包含 emoji 组合序列,建议再引入unicodedata与正则进行 ZWJ 序列处理,避免把一个 emoji 拆成两半。

7.4 一个工程级别的安全建议

后端截断最容易犯的错误是:直接截断后拼上省略号,但忽略了字符边界、代理对和组合字符。建议在任何截断函数里都遵循以下顺序:

  1. 先按 codePoint 遍历,而不是按char遍历。
  2. 遇到代理对、组合字符、ZWJ 序列时,把整个序列当作一个“显示单元”。
  3. 截断前记录原始字符串,如果业务不确定,宁可返回原串也不要产生乱码。
  4. 给截断函数写单测,覆盖:纯中文、纯英文、中文+emoji、maxWidth正好等于边界值的情况。

8. 常见问题与排查思路

字符宽度相关的报错通常不是“抛异常”,而是“显示不符合预期”,所以排查时需要有明确的检查顺序。

问题现象可能原因排查方式解决方案
设置了 width: 200px,输入框还是放不下中文px 和字符宽度没有换算关系用 canvas.measureText 测量实际字符宽度改用 ch/em 或动态测量
用 ch 设置宽度后,英文小写 i 和 W 对不齐比例字体下 ch 只基于数字 0,不代表每个字符检查字体是否为等宽字体切换到等宽字体或动态测量
表格数字列看起来忽宽忽窄数字在比例字体下宽度不一致检查是否设置tabular-nums添加font-variant-numeric: tabular-nums
text-overflow: ellipsis 不生效缺少 overflow: hidden 或 white-space: nowrap检查三者是否同时设置补全样式
后端截断出现“半个 emoji”截断按 UTF-16 char 遍历检查日志输出是否出现孤立代理项按 codePoint 遍历
Python 截断中英文结果不整齐len() 按 Unicode 码点计数,不是显示宽度east_asian_width检查改用 display_width 函数
动态测量宽度和实际渲染有偏差字体设置不一致检查 getComputedStyle().font统一字体字符串

9. 最佳实践与工程建议

前面把概念和实践都讲完了,最后把经验沉淀成一组可以直接执行到团队规范里的建议。

9.1 前端定宽的优先级

在实际代码里,我建议按以下优先级选择字符宽度方案:

  1. 能用em表达中文场景(例如 label 宽度、按钮宽度),优先用em
  2. 能用ch表达等宽字体场景(验证码、编码输入),优先用ch
  3. 需要精确控制时,用canvas.measureText动态计算。
  4. 尽量不要直接用固定px去模拟字符数量,除非你确认字体不会再改。

9.2 动态测量时的字体统一

使用canvas.measureText时,最容易出问题的不是测量本身,而是字体不一致。页面里input的字体和body的字体可能不同;CSS 变量在某些浏览器里解析方式不同。建议封装一个全局文本测量函数,统一读取getComputedStyle,避免在组件里散落字体字符串。

// 文件路径:textWidth.js const textMeasurer = { canvas: document.createElement('canvas'), ctx: null, init() { if (!this.ctx) { this.ctx = this.canvas.getContext('2d'); } }, measure(text, element) { this.init(); const font = element ? getComputedStyle(element).font : getComputedStyle(document.body).font; this.ctx.font = font; return this.ctx.measureText(text).width; } };

后续组件直接调用textMeasurer.measure('测试', inputEl),避免重复创建 canvas。

9.3 后端截断的安全边界

后端截断时,务必要考虑“显示宽度”而不是“字符数量”。如果团队没有统一的截断工具类,建议单独抽一个模块并遵循:

  • 输入为空、maxWidth <= 0 时直接返回原串或空串。
  • 截断结果必须拼接省略号时,省略号本身的宽度也要计入 maxWidth。
  • 对半角/全角宽度采用可配置策略,默认半角 1、全角 2。
  • 对代理对、组合字符、emoji 要额外处理。
  • 写单元测试,防止后续改动破坏边界行为。

9.4 验收清单

一个字符宽度功能开发完成后,可以按这张清单交付:

  • 固定宽度元素在中文、英文、数字三种输入下的表现符合预期。
  • 超长文本能看到省略号,而不是溢出容器。
  • 表格列宽在不同数据量下不会抖动。
  • 后端截断不会出现乱码、半个 emoji、半个代理对。
  • 动态测量逻辑在浏览器缩放下表现稳定(考虑devicePixelRatio和缩放,测量通常不需要处理 DPR,但要注意 CSS 像素与设备像素是两个概念)。
  • 涉及生产环境修改时,先在小范围灰度,再全量发布。

10. 总结与后续学习方向

字符宽度不是单一属性,而是字体、单位、渲染上下文共同作用的结果。前端定宽时,优先用语义单位;精确计算时,用 canvas 测量;后端处理时,按显示宽度截断。这三条线并不是彼此孤立的,一个完整系统通常都需要同时覆盖。

如果你还想继续深入,可以从这几个方向拓展:一是字体度量中em squareascentdescent对行高的影响,这直接关系到多行文本的垂直对齐;二是 CSStext-rendering和字体渲染对宽度的影响,在低端设备上字符间距可能有微小差异;三是 ICU 的 EastAsianWidth 属性,后端做国际化文本处理时建议直接用它作为宽度标准。

建议收藏本文,实际写组件或截断工具时拿回来对照。字符宽度这件事,并不需要靠经验拍脑袋,测量、单位、兜底,三个环节做好,你的页面和接口就不会再因为“宽度”翻车。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/2 14:34:30

在电脑上跑 PS4 游戏:shadPS4 教程与配置全解

在电脑上跑 PS4 游戏&#xff1a;shadPS4 教程与配置全解 【免费下载链接】shadPS4 PlayStation 4 emulator for Windows, Linux, macOS and FreeBSD written in C 项目地址: https://gitcode.com/GitHub_Trending/sh/shadPS4 shadPS4 是一款用 C 写的 PS4 模拟器&#…

作者头像 李华
网站建设 2026/9/2 14:33:22

STM32继电器控制全解析:从驱动电路到智能台灯实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/2 14:31:44

Python实战:基于字符串匹配与时间轴分析的歌词同步跟唱检测器

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/2 14:31:07

从源码到可运行:Ryujinx C Switch 模拟器的本地构建与验证清单

从源码到可运行&#xff1a;Ryujinx C# Switch 模拟器的本地构建与验证清单 【免费下载链接】Ryujinx 用 C# 编写的实验性 Nintendo Switch 模拟器 项目地址: https://gitcode.com/GitHub_Trending/ry/Ryujinx Ryujinx 是一款用 C# 编写的开源 Nintendo Switch 模拟器。…

作者头像 李华
网站建设 2026/9/2 14:30:38

WorkBuddy接入Hy4 preview本地运行:从配置到实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/2 14:30:11

3 条命令把微信聊天记录存成文档:WeChatMsg 完整导出指南

3 条命令把微信聊天记录存成文档&#xff1a;WeChatMsg 完整导出指南 【免费下载链接】WeChatMsg 提取微信聊天记录&#xff0c;将其导出成HTML、Word、CSV文档永久保存&#xff0c;对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_Trending/we/We…

作者头像 李华