我已经阅读了CSS - 让无衬线字体模仿等宽字体,但是CSS规则
letter-spacing
似乎还不够:
如何从标准无衬线字体模仿等宽固定字体?
这并不完美:
.text {
font-family: sans-serif;
letter-spacing: 10px;
}
<div class="text">
ABCDEFGHIJKLMNOPQR<br>
STUVWXYZ0123456789
</div>
letter-spacing
只是在所有字母之间均匀地插入空格(...因此得名)。letter-width
这样的 css 属性,但它不存在。
除了在字体编辑器中更改实际字体规格并编译新字体之外,您还可以通过 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 = ' ';
} 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>
每个字符都将包含在具有
inline-block
显示属性的范围内。
此外,所有字符均通过
text-align:center
居中。
上面的脚本还会比较所有字符的宽度,将最大的宽度设置为跨度宽度。
不可否认,这不是很方便
但这种方法可能足以满足设计/布局的目的,并且不会更改实际的字体文件。
如片段所示:
在等宽字体中,最宽的字母(如“W”)会被挤压(不会扭曲)
而较瘦的人喜欢
“i”在视觉上得到拉伸(例如通过添加底部衬线)。
因此,正确的等宽字体是完全不同的,并且无法真正模拟。
我花了太多时间试图找到一种好的等宽字体,它可以与多个字母一起使用,并且具有我想要的外观。这些是我找到的解决方案(按推荐顺序):
letter-spacing
模拟简单的等宽字体。