【问题标题】:Make replacement characters from non-monospace fonts appear with correct width when used as monospace font当用作等宽字体时,使来自非等宽字体的替换字符以正确的宽度显示
【发布时间】:2014-10-10 05:58:45
【问题描述】:

Web 浏览器用另一种字体中的字符替换字体中缺失的字符(通常是箭头、图形符号,在我的特定用例中是 unicode 字符“≫”(U+226B))。如果您使用的是等宽字体,则替换字符(大部分时间)来自比例字体,并且会弄乱在使用等宽字体时在许多情况下需要的严格网格图案。

例如,在我的浏览器中,这是一团糟:

<pre>
012345
 1 |
 a |
 Ö |
 % |
 ≫ |
 2 |
 b |
 X |
 & |
</pre>

“≫”之后的管道符号与其他符号不对齐(与我机器上安装的字体)。

有没有办法确保浏览器将替换字符缩放到正确的宽度?

如有必要,JavaScript 解决方案也可以。

【问题讨论】:

  • 如果您提供标记以重现问题(您使用的字体和那些特定字符)会很好。
  • 只是字符“≫”造成了所有问题吗?如果是这样,我注意到如果您在 HTML 中编写 &amp;raquo;,那么对于许多字体,它已经解决了问题。或者,如果您无法更改 HTML 代码,您可以使用一个小脚本来替换该字符,即 document.body.innerHTML = document.body.innerHTML.replace('≫', '&amp;raquo;');
  • @Salman:我提供了一个示例,请参阅我的编辑
  • @Niffler: »是一个不同的字符:» vs. ≫

标签: javascript html css fonts


【解决方案1】:

这充其量只是部分答案,但也许对某些人会有所帮助。在您的 CSS 字体堆栈中,您可以包含具有良好 unicode 覆盖率的等宽字体。例如,OS X 中的 Courier New 包含超过 1200 个字形,我猜这些字形包括大多数有用的 unicode 字符。如果您将其列在字体堆栈中的主要字体之后,那么您的主要字体中缺少的那些字符至少具有一致的宽度。

当然,如果主字体的宽度与备用字体的宽度不同,这并不能真正解决问题。如果幸运的话,您也许能够找到具有相同宽度且具有足够 unicode 覆盖率的备用字体,在这种情况下您可以按原样使用它。否则,我认为您没有简单的解决方案。在这种情况下,我可以想到几个替代方案。

  1. 如果许可证允许,您可以修改备用字体的宽度,使其与您的主要字体相匹配。
  2. 如果您事先知道要显示哪些 unicode 字符,可以将它们包装在 &lt;span&gt; 标记中并调整样式以匹配主要字体的宽度。

恐怕无论如何都不是一个简单的解决方案。

附:您可能想要编辑您的标题。我认为您的意思是“mono-spaced”,因为“monotype”是一种类型铸造厂。

【讨论】:

  • @Stephen Thomas:“包括大多数有用的 unicode 字符”......除非你是中国人:p
【解决方案2】:

你愿意做多铁杆?
这是一个将文本的每个字母包装在给定宽度的跨度中的代码:

var container = document.getElementsByClassName('mymonotext');
if (!container.length) {
    throw new Error('.mymonotext is not found');
}

container = container[0];
container.normalize(); //Merge all the adjacent text nodes inside a container (see https://developer.mozilla.org/en-US/docs/Web/API/Node.normalize)

var currentNode = container.firstChild;
for (var i = 0, len = currentNode.textContent.length; i < len - 1; i++) {  
    var range = new Range(); //Create a range

    //Insert a first char into a range
    range.setStart(currentNode, 0); 
    range.setEnd(currentNode, 1);

    var wrapper = document.createElement('span');
    wrapper.className = 'letter';

    //Wrap the range with a span tag
    wrapper.appendChild(range.extractContents())
    range.insertNode(wrapper);

    //Detach the previous range and shift current node
    range.detach();
    currentNode = currentNode.nextSibling.nextSibling;
}

包装标签的样式:

.letter {
    width: .5rem;
    display: inline-block;
    overflow: hidden;
}

在 jsfiddle 上也是一样:http://jsfiddle.net/enwyoy4y/
(使用后果自负,yada-yada,不支持IE8等)。

【讨论】:

  • 它会切断字母而不是拉伸它们,有没有可能解决这个问题?另外,我只想将它应用于符号列表(而不是每个字母) - 是否可以确保“宽度”等于普通等宽字符的宽度?
  • 您可以尝试将span width设置为1em,应该接近字母宽度。根据您的具体情况进行调整。
  • 我不知道任何拉伸字符的好方法。如果您知道字体支持的完整字符列表,则可以从包装中排除已知符号。
  • 减小字体大小,直到字符适合为止。字母宽度应通过 JavaScript 计算,您必须记住字母宽度可以是小数(例如 8.4px 而不是 8)。
【解决方案3】:

等宽字体中字符的前进宽度对于特定字体是固定的,但对于不同的等宽字体可能会有所不同。如果您限制自己使用特定的等宽字体(在网页上,这仅在使用 @font-face 时才有意义,因为没有在所有计算机上都可用的等宽字体),您可以找出它的提前宽度(例如使用字体检查器程序,或进行一些测试),然后将元素缩放到该宽度。

然而,你不能让字体大小取决于元素的宽度,除非有一些 JavaScript 编程,所以如果你的问题只是一个字符,使用图像是最简单的。以某种大字体书写字符,截取屏幕截图,然后使用您仅设置宽度的img 元素缩放图像。或者,您可以创建尺寸恰到好处的图像,但如果您稍后更改字体(因此宽度也可能发生变化),这将不太灵活。

【讨论】:

  • Javascript 没问题,这就是为什么我在问题的标签列表中包含了 javascript。
猜你喜欢
  • 1970-01-01
  • 2013-01-09
  • 2019-04-08
  • 1970-01-01
  • 2021-10-09
  • 2020-12-17
  • 2022-09-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多