字符宽度
文本显示中每个字符在水平方向上占据的空间大小。包括全角 (2 列宽) 与半角 (1 列宽) 的区分,以及比例字体中的可变宽度。
字符宽度 (character width) 是指文本显示在屏幕或纸面上时,每个字符在水平方向上占据的空间大小。日语的文本处理中,"全角"与"半角"这两个概念根深蒂固,一般认为全角字符占据半角字符两倍的宽度。这一区分定型于 1 字节表示的字符与 2 字节表示的字符并存、并在等宽字体的终端上显示的时代。需要注意的是,全角与半角本来讲的是"显示上的宽度",与在字符编码上是否算 1 个字符是另外一根轴。全角的"A"和半角的"A"在 Unicode 中都是 1 个字符 (1 个码位)。
Unicode 用 East Asian Width 属性对字符宽度进行分类。F (Fullwidth) 为全角,H (Halfwidth) 为半角,W (Wide) 为东亚的宽字符 (汉字、平假名、片假名等),Na (Narrow) 为窄字符 (ASCII 英文数字等),A (Ambiguous) 为宽度随上下文变化的字符,N (Neutral) 为两者都不属于的字符。这个 Ambiguous 类别很麻烦,希腊字母的"α"、西里尔字母的"А"、带圈数字的"①"、带重音符的"é"等都包含在内,在面向东亚的环境中按全角处理,在面向欧美的环境中按半角处理。同一个字符串也会因终端的设置而改变显示宽度,因此用制表线或符号来拼表格时会错列。想避免错列,就不要把属于 Ambiguous 的字符用于装饰,列对齐则用不依赖字体宽度的方法 (HTML 中用表格或网格) 来做,这样才可靠。
比例字体中,每个字符的宽度各不相同。"W"和"m"拥有"i"或"l"的数倍宽度,而这个比率会随字体而变化。因此,用比例字体显示的文本的横向宽度,无法仅凭字符数来预测。同样是 10 个字符,"WWWWWWWWWW"和"iiiiiiiiii"的显示宽度相差很大。如果需要知道实际的宽度,只能用所使用的字体去测量。在浏览器上,可以用 canvas 的 measureText() 以像素为单位取得绘制宽度。
等宽字体 (monospace font) 中,所有字符拥有相同的宽度。编程用的代码编辑器和终端之所以使用等宽字体,是因为字符的位置对齐很容易,缩进和列对齐不会错乱。日语的等宽字体中,全角字符被设计为恰好是半角字符的两倍宽度。
字符计数与字符宽度的关系在显示布局的设计中很重要。例如,在数据库的列表界面上为"姓名"列确保 20 个字符份的宽度时,如果全是全角字符则能放 10 个字符,全是半角字符则能放 20 个字符。实际的数据是全角与半角混在的,因此需要按最坏情况 (只有全角) 来设计宽度。
在 Web 设计中,CSS 的 ch 单位是以"0" (数字零) 的宽度为基准的相对单位。指定 width: 40ch 就大约是 40 个字符份的宽度。不过,比例字体中不同字符的宽度各异,所以 ch 单位终究只是个大致标准。若是日文文本,能以日文的 1 个字符为基准的单位更为直观。em 是表示元素的字体大小本身的单位,日文的字面被设计为填满字体大小,结果就与全角 1 个字符的宽度几乎一致。想更严格地按日文基准来排版时,可以使用 ic 单位。它是把"水" (U+6C34) 的字符步进宽度定为 1 的单位,width: 20ic 就是日文 20 个字符份的宽度。选用的大致标准是:以西文为主的正文用 ch,想对齐日文的列数用 ic,不依赖字体的留白计算用 rem。