简体   繁体   English

如何用可变宽度字体模仿等宽字体?

[英]How to imitate a monospace font with a variable-width font?

I have read CSS - Make sans-serif font imitate monospace font but the CSS rule letter-spacing doesn't seem to be enough:我已阅读CSS - 使无衬线字体模仿等宽字体,但 CSS 规则letter-spacing似乎不够:

在此处输入图像描述

How to imitate a monospace fixed font from a standard sans-serif font?如何从标准无衬线字体模仿等宽固定字体?

This doesn't work perfectly:这并不完美:

 .text { font-family: sans-serif; letter-spacing: 10px; }
 <div class="text"> ABCDEFGHIJKLMNOPQR<br> STUVWXYZ0123456789 </div>

I've spent too much time trying to find a good monospaced font that works with several alphabets and had the look I wanted.我花了太多时间试图找到一种可以与多个字母一起使用并具有我想要的外观的好的等宽字体。 These are the solutions I found (in order of recommendation):这些是我找到的解决方案(按推荐顺序):

  1. Find a monospaced font that you like and use that.找到你喜欢的等宽字体并使用它。
  2. Use a font editor and change all the letters to the same width (there might be a Python program that can do that, but I haven't tried it).使用字体编辑器并将所有字母更改为相同的宽度(可能有一个 Python 程序可以做到这一点,但我没有尝试过)。 But changing a font to monospaced will not look as good, there are a lots of craftsmanship in creating each letter so it will fit properly in the monospaced box.但是将字体更改为等宽字体看起来不太好,创建每个字母都有很多工艺,因此它可以很好地适合等宽字体。
  3. Use letter-spacing to simulate a simple monospaced font.使用letter-spacing来模拟简单的等宽字体。

letter-spacing just evenly inserts whitespace between all letters (...hence the name). letter-spacing只是在所有字母之间均匀插入空格(......因此得名)。
It won't normalize characters/glyphs to have the same widths.它不会将字符/字形标准化为具有相同的宽度。
We would need a css property like letter-width which doesn't exist .我们需要一个 css 属性,比如不存在letter-width

Apart from changing the actual font metrics in a font editor and compiling a new font you could split up all letters into an array of <span> elements via javaScript.除了在字体编辑器中更改实际字体规格和编译新字体之外,您还可以通过 javaScript 将所有字母拆分为<span>元素数组。

 emulateMonospace(); function emulateMonospace() { let monoWraps = document.querySelectorAll(".toMonospace"); monoWraps.forEach(function(monoWrap, i) { //remove all "\n" linebreaks and replace br tags with "\n" monoWrap.innerHTML = monoWrap.innerHTML.replaceAll("\n", "").replaceAll("<br>", "\n"); let text = monoWrap.textContent; let letters = text.split(""); //get font-size let style = window.getComputedStyle(monoWrap); let fontSize = parseFloat(style.fontSize); //find maximum letter width let widths = []; monoWrap.textContent = ""; letters.forEach(function(letter) { let span = document.createElement("span"); if (letter == "\n") { span = document.createElement("br"); } if (letter == ' ') { span.innerHTML = '&nbsp;'; } else { span.textContent = letter; } monoWrap.appendChild(span); let width = parseFloat(span.getBoundingClientRect().width); widths.push(width); span.classList.add("spanMono"); span.classList.add("spanMono" + i); }); monoWrap.classList.replace("variableWidth", "monoSpace"); //get exact max width let maxWidth = Math.max(...widths); let maxEm = maxWidth / fontSize; let newStyle = document.createElement("style"); document.head.appendChild(newStyle); newStyle.sheet.insertRule(`.spanMono${i} { width: ${maxEm}em }`, 0); }); }
 body{ font-family: sans-serif; font-size: 10vw; line-height: 1.2em; transition: 0.3s; }.monospaced{ font-family: monospace; }.letterspacing{ letter-spacing:0.3em; }.teko { font-family: "Teko", sans-serif; }.serif{ font-family: "Georgia", serif; }.variableWidth { opacity: 0; }.monoSpace { opacity: 1; }.spanMono { display: inline-block; outline: 1px dotted #ccc; text-align: center; line-height:1em; }
 <link href="https://fonts.googleapis.com/css2?family=Teko:wght@300&display=swap" rel="stylesheet"> <h3 style="font-size:0.5em;">Proper monospace font</h3> <div class="monospaced"> WiWi</br> iWiW </div> <h3 style="font-size:0.5em;">Letterspacing can't emulate monospaced fonts:</h3> <div class="letterspacing"> WiWi</br> iWiW </div> <hr> <h3 style="font-size.0;5em;">Text splitted up in spans</h3> <div class="toMonospace variableWidth"> ABCDEFGHIJKLMNOPQR<br> STUVWXYZ0123456789<br> </div> <div class="toMonospace variableWidth teko"> ABCDEFGHIJKLMNOPQR<br> STUVWXYZ0123456789<br> </div> <div class="toMonospace variableWidth serif"> This is<br> not a<br> Monospace<br> font!!! </div>

Each character will be wrapped in a span with an inline-block display property.每个字符都将被包裹在一个带有inline-block display 属性的 span 中。

Besides all characters are centered via text-align:center .此外,所有字符都通过text-align:center

The above script will also compare the widths of all characters to set the largest width as the span width.上面的脚本还会比较所有字符的宽度,将最大宽度设置为跨度宽度。

Admittedly, this is not very handy诚然,这不是很方便
but this approach might suffice for design/layout purposes and won't change the actual font files.但这种方法可能足以用于设计/布局目的,并且不会更改实际的字体文件。

As illustrated in the snippet:如片段所示:
In monospace fonts the widest letters like "W" get squeezed (not distorted) whereas the thinner ones like "i" get visually stretched (eg by adding bottom serifs).在等宽 fonts 中,像“W”这样最宽的字母会被挤压(不变形),而像“i”这样的较细的字母会在视觉上被拉伸(例如,通过添加底部衬线)。

So proper monospace fonts are completely different and can't really be emulated.所以适当的等宽 fonts 是完全不同的,不能真正被模仿。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM