letter-spacing
just evenly inserts whitespace between all letters (...hence the name).
It won't normalize characters/glyphs to have the same widths.
We would need a css property like letter-width
which doesn't exist.
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.
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>
Each character will be wrapped in a span with an inline-block
display property.
Besides all characters are centered via 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 (e.g by adding bottom serifs).
So proper monospace fonts are completely different and can't really be emulated.