Hacker News new | past | comments | ask | show | jobs | submit login
Texture Healing for Monospace Fonts (github.com/githubnext)
253 points by notpushkin on Nov 10, 2023 | hide | past | favorite | 97 comments



It bothers way me more that the same glyph can differ within the same word than it satisfies me that the glyphs are very slightly more proportional. The third "m" in the "minimum" example being narrower than the "m"s adjacent to the two "i"s makes my brain itch. Same for the "i"s in "miniature". Makes me feel like I'm looking through a fish-eye lens, or that my glasses prescription is off.


I think this all makes a lot more sense when seen in a practical context rather than the blown-up examples in the feature documentation.

Take a look at the code editor examples on the main site for Github Monaspace: https://monaspace.githubnext.com Scroll down to the "Five Fonts" section and try unchecking the texture healing toggle.

The fisheye effect you get when looking at the font in 200pt goes away at 16pt, and in the context of a busy code block, has the effect of smoothing out the visual rhythm of the characters with only a minor disruption of the monospace grid. Perhaps it's not for everyone (it is a trade-off), but I think it's a smart compromise.


I can’t help but think that the example in that page has used ‘timing’ so much to deliberately show off texture healing - it’s a great example because the ‘m’ can expand in both directions and the ‘i’s end up looking the same.

I suspect the state where different width variants of the same letter are close to each other would happen a lot more in the real world.


Right, and they show it above "time" where the "e" can't "give the space" so you can understand if it actually bothers you (probably not unless you stop and stare):

    const timing_end_m_ = () => {
      let timing_end = new Date();
      let time_spent = timing_end - timing_start; // in ms


After seeing it in a larger context like that, I'm even more in agreement with OP. The weirdly random letter alignment screws with my brain much more than I thought from just the localized examples in the topic link.

I'll stick to the consistent design for a slightly less aesthetic experience for that reason alone.


This might be an autism thing for me but turning on texture healing on that page is so horrible it actually made me flinch.

The fact that the "i" in "terminal dimensions" and the "i" in "width" aren't underneath each other makes it look like my monitor is broken or something. It's like someone has done it on purpose to mess with me.


I think this is a fun innovation and I might try to use it in my terminal, but for coding, the real solution should be obvious: use a proportional font.


This seems to be an unpopular opinion, but proportional fonts are great.

One question people sometimes ask is, "How can you code in a proportional font? How do you line things up in columns?"

The answer is you don't. For example, the Black code formatter for Python completely eschews column alignment of this sort:

  foo.bar(one,
          two,
          three)
(Imagine that the words were long enough that the whole thing wouldn't fit on one line.)

Instead, Black formats it like this:

  foo.bar(
      one,
      two,
      three
  )
No column alignment, only indentation. Code formatted like this is equally readable in a proportional or monospaced font. You don't need monospaced fonts!

I've read and written all my code in proportional fonts for close to 20 years. My current one is Trebuchet++, a variant of Trebuchet MS that I customized in FontForge.

Trebuchet MS is pretty good on its own. For example, all of the "confusable" glyphs are easy to distinguish. And it renders very nicely on a high-DPI display.

Its tilde is pretty bad, though. It's tiny and almost looks like a hyphen. So that was the first thing I fixed, putting in a better tilde.

Then I experimented with spacing for the _ and . glyphs. I added negative margin on both sides of the _, while keeping its width. And I added positive spacing on both sides of the . glyph. Consider code like this:

snake_case_name.another_snaky_name()

These spacing changes have the affect of pulling the individual words in each name closer together, while increasing the separation between the two names.

It is subtle, but to my eye it helps readability.

Next up will be to add some positive margin inside the three pairs of brackety things: (), [], {}. I have always found that it helps readability to add a space inside parens and such, but most contemporary code formatters prohibit this. With a proportional font I can tweak the font to put some visual spacing there.


"If you stop doing things which derive benefits from monospaced fonts, then you can get away with a proportional font."

Thanks, but no. Your foo.bar() example is significantly less readable the way Black formats it.


I don't like the extra lines, but also I almost never care if "one" is exactly lined up with "two". You can use proportional fonts with the first example too.


> can use proportional fonts with the first example too.

what, how? Wouldn't the number of spaces you'd need to prefix lines 2 and 3 with vary between fonts?


Not if you don't care about "one" exactly lining up with "two".

  foo.bar(one
        two,
        three) //this is fine, and slight drift on different fonts is also fine
I would have demonstrated in a proper proportional way but HN destroys NBSP.


That was the whole point.


You dismissed the idea as "if you stop doing thing which benefit from monospaced fonts", suggesting that monospaced fonts are better in this situation.

My argument is that both fonts are just as good in this situation, and monospaced fonts aren't benefiting here. You don't need monospaced fonts to use formatting 1, you can just choose formatting 1 and then use either kind of font.

Doesn't that mean I disagree with your post?


Having the "one" line up with the "two" is the benefit here, and the point of the monospaced font. If you don't care about that, fine. But objectively lots of people do.


Well I'm saying that it does still line up in a reasonable sense, at least from the perspective of someone that would use a proportional font at all and isn't looking for a grid.

It's important to note that I'm not comparing monospace versus proportional. I'm saying that "formatting 1 with proportional font" isn't really worse than "formatting 2 with proportional font". Both of them are going to have problems from someone that really likes monospacing.


"If you stop doing things which derive benefits from monospaced fonts, then you can get away with a proportional font."


No, that's the opposite of my point.

"If you already decided to have a proportional font, you don't need to stop doing any things."

My argument is that "need to stop doing X" is not true for either kind of font.


That formatting is extremely common in dynamic languages. Are you from the C/C++ world?


For me it's not about lining things up in columns as much as it is about column widths. So, for example, hitting up or down, I know which character the cursor is going to go to (which means I can string keypresses together and do them in a fluid movement). Putting in a hard limit for line lengths (which is very important to me, I know opinions on this differ) means that limit can be drawn as a literal line on the UI (which in turn means I know how small I can resize the editor pane to be). Similar lines with slightly different values (e.g. 'x', 'y' and 'z') will line up so the different values are underneath each other everywhere they appear in the line (also those lines will be the same length which reassures me those lines are the same outside the variables/values).


That's a good link. I think the text-healing mode with VS Dark Theme is clearly the most readable


Yup, I unfortunately have to agree. It's a cool idea, but when I type "gimme" in the editor, the two adjacent m's are different widths, and it looks sooo wrong.

Interestingly enough, the fact that letterforms change as I type doesn't bother me the way I thought it would -- turns out I'm already kinda used to it from ligatures.

So points for being a clever idea to try out, but unfortunately what it does to a word like "gimme" just makes it a non-starter. Let's face it -- lowercase m's in monospace will always be ugly and cramped, but at least they're consistently so.


But is this a fundamentally bad idea, or is it, like kerning in general (which can require thousands of pairs to be defined), something that just needs more work?

It's not like this is limited to just a few pairs of letters like 'mi', or just pairs - if you've seen Fontemon https://www.coderelay.io/fontemon.html you know the sky is the limit for what the rewrites can do!


It's a fundamentally bad idea. I think for anything to look monospace for me the following two properties are non-negotiable.

1) Horizontal spacing needs to align vertically between glyphs of the same letters on separate lines. This is the example I give elsewhere of a letter "i" being in a very slightly different position than the same letter just two lines above it. I personally find this extremely disturbing and unpleasant to look at in monospace.

2) The glyph of a letter needs to be the exact same between instances of the same letter that are in any kind of visual proximity. This is the "gimme" example the parent of your comment gives. AnyThinG ElSe LoOkS lIkE jumblycase. Which I think we can all agree is just plain horrible.


Specifically for monospace fonts, it's not obvious to me how any further work could fix it.

The same letterform having different widths just looks bad and wrong.

It's not like kerning, which always looks good when done well (for proportional fonts).


> It's not obvious to me how any further work could fix it.

In "gimme" you could have a rule that when any character is next to itself both occurrences must have the same width. Wouldn't that fix the "gimme" example?


What about distributing the space amount more that one letter, and ensuring no two of the same letter are ever different. You'd allow things to get out of sync and not be on a perfect grid, so long as you could align everything at key points where a line has the same character on two successive lines, or some other case where you know you need alignment.

Everything else would just look like a proportional font.

Maybe it would influence coders too much and subconsciously make them choose names that line up well though...


The effect is not as pronounced and almost indistinguishable in xenon radon and krypton. It's just neonand argon that look horrible in gimme.


Yeah... I hate this. Solves a "problem" for someone with a different type of OCD than mine.


This is a solution looking for a problem.


This is going to make a lot of brains itch.


My brain seems to scan for differences to familiar patterns. For code that just doesn't look right. When I see stuff like this, it feels like finding a bug/typo. So a lot of false alarms.

Maybe my brain would adjust after a while. And maybe I'm also different to other people. I think my reading skills are a bit skewed towards recognizing words/patterns instead of reading characters (probably some form of compensation for my dyslexia).


Tried it here: https://monaspace.githubnext.com/

It might be nice for reading code, but for editing code it feels weird that glyphs change their size while you type.

Also readability wise I'm not convinced. In the example there is a combination like "_m_", in this case the lette m is much nicer to read. But then i typed "mml", which makes the two m's very different looking. Also the line number 10 on top of 11 looks weird.


> It might be nice for reading code, but for editing code it feels weird that glyphs change their size while you type.

Applying display typography techniques to code is an objectively bad idea for both reading and writing.

They even enable ligatures by default on the demo which is far worse. For those of us who actually have to get work done and not just fetishize code and fawn over aesthetics, it's a fundamental requirement that every single character be as unambiguous and consistent as possible.


Please stop diluting words like objectively for things that you just feel strongly about.


I suppose you've never dealt with encoding issues. Encoding issues are very common, funnily enough, when you're writing code meant to handle display text. Not just web pages, but even native apps that must support almost any language that isn't English. Not all work is lighthearted when it comes to fixing these mistakes, nor is the testing reliable. Accessibility is a huge deal and can bring about lawsuits. Really, it even has security implications. If one is this sloppy about fonts I doubt there's much validation going on elsewhere, yet injection attacks should be trivial to mitigate. Why overcomplicate this? No mere font in your editor is going to distinguish between the string literals for the user and the rest of the code being displayed to the programmer.

I'm not misusing these words for hyperbole. We're talking about text. Words like "literal" and "objective" belong here. At this stage of the game, few subjective decisions are left to tinker with in programming. I'm sorry if that sort of thing brings you joy. Get another hobby.

It's objectively bad to alter the visual presentation of font glyphs for non-functional purposes. If a programmer sees the same glyph with varying width, they have to wonder if it's the same underlying character. If a ligature is applied, they have to wonder if it's the same character being displayed. That's a huge waste of time for little to no benefit. We are very far away from these concerns being a thing of the past. The cognitive load must still sometimes fall back on human inspection. A cute font shouldn't prevent you from doing that, nor should anyone need to break out the hex editor to be sure. This simple knowledge cannot die off into obscurity yet.

If y'all want pretty code it must be done at the text encoding and compiler level (invent a new keyboard layout while you're at it!), not in the fonts... but that too would just repeat the sins of the past. :)


This ship has literally sailed, hyperbole continues to affect our language whether we want it or not.


I think it became more common, especially public communication became much stronger (politics, news, corporate communications).

In human to human communication those changes don't necessarily apply. Even the politicians that are most violent with their words in speeches are often completely "normal" once the cameras are turned off.


None of the subjective preferences here are “objective”, and the added insulting language for people who disagree makes it worse, not better.


Ligatures are great if done right. E.g. the set in Fira Code gives me a 2 character wide ≠ instead of != so it retains the monospace widths.


All "coding" ligatures in all monospace fonts work like that.


I get my work done with ligatures. That's fine for me.


I think they should adjust their rules so that when a character is next to itself, both occurrences must use the same variant.


Huh, on a linux desktop the "own voice" example just seems to change height and weight and nothing else. (Still horrible, but it just looks like it's "breathing".) On mobile (android chrome), it looked like it was changing in more dimensions, I'd almost call it "writhing". I hope "reduced animation" turns this kind of thing off (but I couldn't find the setting in chrome at a quick look...)


That seems like Chromium is trying to do some hinting, which would ideally make the glyphs fit better to pixels, but it corrupts smooth transitions.


> But then i typed "mml", which makes the two m's very different looking.

Agreed. I find this even more noticeable and distracting with narrow characters; e.g. in “llm”, one of the “l”s reads like “1” to me.


I was halfway through reading this trying to figure out if I wanted to give up my existing code ligatures, but then I hit the code ligatures section, and now I'm hooked


I'm not sure if the name “Texture Healing” is descriptive enough (perhaps I'm not that much of a typography nerd I think I am!), but I love the idea. Basically it resolves pairs or triplets of monospace letters to make some of them wider when adjacent letter can be made narrower instead.

Another variation on that theme are “duospace fonts”, like iA Writer Duo [1]. Those use two character widths instead of one (i.e. wide characters are always 1.5x wider than narrow). I think this could work for code, too.

[1]: https://ia.net/topics/in-search-of-the-perfect-writing-font


I've never heard "texture" used this way, although that's not saying much. My personal opinion would be that it's not the right word. I have heard the term “color” used in typography to describe the balance of positive and negative space on the page in phrases like “even (or uneven) color”. But although that feels closer, it also doesn't feel quite right in this case. It reminds me of the subtle changes in tracking and glyph width that some justification engines perform:

“Most of the type set in the past five hundred years is justified type, and most of it has been justified line by line, by the simple expedient of altering the space between the words. There are, however, better ways. Scribes justify text as they write by introducing abbreviations and subtly altering the widths of letters. Gutenberg replicated the feat by cutting and casting a host of abbreviations and ligatures along with multiple versions of certain letters differing modestly in width. In the early 1990s, Peter Karow and Hermann Zapf devised a means of doing much the same in the digital medium[.] [...] Another thing computer software can do – because Karow taught it how – is justify text by making subtle alterations in the spaces within letters as well as those between letters and words.”

The Elements of Typographic Style, fourth edition, by Robert Bringhurst, pp 191–192.


I think "texture" makes sense, if only by analogy to the calligraphic hand Textura, or the etymological derivation of "text" itself.


I'd call it dynamic monospace.


Duospace fonts are limitedly proportional, but still with no upsides of monospace fonts. Rather than that, I recommend something more proportional like iA Writer Quattro, Input Sans and Recursive Sans. https://input.djr.com/ https://www.recursive.design/


Hmm -- I do not understand what is the use case for this. For best design, clearly, I'd use a proportional font. So whenever I want a monospace font, there are reasons that exclude proportional fonts. An obvious reason would be a grid that the letters need to be arranged in (for whatever reason). But then, I can only imagine that any smart rearrangement of letters out of their grid box will be unwanted, because it interfere with that grid. Instead, stupidly simple letter placement will be what I want.

I have an idea for an advanced technique that yields much better visual appearance (but that is also not want you'd want, for the same reasons): instead of just focussing on pairs of letters (so primitive!), consider whole words and optimise their letters' shape, width, and horizontal position, but keep the size of box of the word. I call that 'equilibrium texture healing'.


In this technique the letters do not leave their grid box. A wide letter next to a narrow letter will at most push hard up against the edge of its box (usually there has to be white space there so that, e.g. mm doesn’t become one glyph)


The text states that, but then in the Healing Examples section [0], the "m" in "filming" clearly spills over its left border line.

Is that just a poorly drawn/incorrect example graphic?

[0] https://github.com/githubnext/monaspace/blob/main/docs/Textu...


It still makes lines with N characters take up the same amount of space, honoring the fundamental characteristic of monotype.


It seems to be a weird mix of half-assed kerning and scaling mixed together.

Perceptually, based only on playing with it a minute, it seems to improve legibility a bit (but not as much as a proportional font would be) but also visually breaks the alignment a little sometimes.

Not sure it's a worthwhile overall, but interesting.


I think it is intersting and can be improved


This is great as it improves glyph/bg contrast when possible (i.e. readability of individual glyphs) and it makes the text's texture look more uniform (hence the name).

Things people here seem to misunderstand:

1. The grid is not affected. The resp. letters stay within their grid-aligned bounding boxes.

2. Letters may change while you type but this is not noticeable in practice. I have a 3.2x2k 15" screen on my laptop. At my editor's effective font size of around 20px (capital letters, from baseline to top) the change in shape is about a pixel for something like the letter 'm'.

Caveat: I'm an ex-typographer. As such I not only do care way more about these things than the average engineer. I'm also more aware that these things do have an effect on eye/brain/visual system strain that is possibly very hard to quantify.

But legibility of a text is a thing. And the font with its properties is one very important factor (font width/kerning/line height are equally important in that regard -- nevertheless).

Edit: typos


> 1. The grid is not affected. The resp. letters stay within their grid-aligned bounding boxes.

Their own examples literally show that this isn't the case. Just look at the "filming" example, with the "m". In addition, their five fonts showcase shows that letters that "need space" can overbound.

I think it's accurate to say that a word respects it's bounding box, but interior glyphs don't necessarily. Unless their own examples are somehow misrepresentative.


> Their own examples literally show that this isn't the case. Just look at the "filming" example, with the "m". In addition, their five fonts showcase shows that letters that "need space" can overbound.

They don't, it's an optical illusion. That's the whole point. Read the whole text and/or open the example images which show the different versions of 'm' and 'i' side by side and measure their bounding boxes. Or open the fonts in a font editor.

They have all the same width.

Think about the implications if what you said were true. The font (or typeset engine) can't know how many pairs or triplets of these special case letter combos are in a word or a line. So you can't make sure a word stays the same width. It's impossible. There is no 'lookahead' the font designer can use to ensure this.

The only option really, to respect the grid, is staying inside equally spaced bounding boxes that are the core property of a monospaced font.


> The only option really, to respect the grid, is staying inside equally spaced bounding boxes that are the core property of a monospaced font.

...or just making sure your immediate neighbors and yourself equal their previous total bounding box? "Needs space" glyphs borrow from "gives space" glyphs, but only in the immediate vicinity not in totality. Spaces are neutral characters.


I've been really enjoying Intel One Mono which seems to solve this by adding more space around most characters (two extra pixels per side at the size I like, about 17px capital letter top to bottom if I counted right) except the m and w (I think, I didn't check everything; they still get one pixel on each side). It also has a low x-height and tall line height and doesn't even try to work at small font sizes but it looks really nice if you make it big enough. Comparing with my previous favorite DejaVu Sans Mono (aka Bitstream Vera Sans Mono) it seems like all the extra space visually evens out the letters and it works well without this kind of adjustment.


I think monospace is good for code. It allows me to write two lines of code perhaps one commented out, and easily see which characters are different in which position.

So it's not only readability, but also "comparability".


The thing I'm curious to see is this font feature being used while typing. I feel like the characters kind of "jiggling" behind your cursor as you type is going to be kind of weird, no?


From testing out the monaspace fonts, it’s really not very noticeable. It only affects one character back, and they only do it for the really egregious cases, so during normal typing, you barely see it happening. That’s similar to normal ligatures e.g. ffi, where you typically don’t notice the swap.


We're at a point where the places that monospace prevails (code editors, obviously) have been festooned with so many other visual intrusions while typing that that additional jank the jiggling adds will be lost in the noise.


You see a bit of movement when writing "mimimimimi..." I don't know if I would have noticed that during "normal" editing.

But I don't like the font, so no real tests ;)


I feel like this would drive me nuts when dealing with code, CSVs, or other kinds of data I'd commonly be viewing with a mono font. Two adjacent rows nearly identical rows might look more different than they really are, say because an "im" changed to an "wm" and the "m" is moving around.

That's not to say it's bad at all, just that I think it wouldn't be right for how I'd mostly likely be using such a font.


I tried out Monaspace but felt that the fonts were a bit thin for my QHD monitor I use as my primary display. It might be better on a retina/4k monitor though.

Perhaps fonts are something you get used to after some time using it, but I ended up switching back to my favorite font, Input Mono (which, as a coding font, isn't actually monospace, so it brings a bunch of cool features and doesn't need to do texture healing).

https://input.djr.com/info/


Input Mono is actually monospace. Input Sans and Input Serif are the ones that aren’t (merely monospace-inspired).


Monospace can be parameterized, you can just make the font weight larger.


Good tip! I might try this variable width idea. Seems a bit out there.


Should have used the name “Textual Healing”.


Wow I didn't think I would but I really hate this.

Not having the glyph of a specific letter always align with itself vertically in a monospace font is just horrendous. It's so unpleasant for me to look at it makes the whole horizontal spacing thing moot.


I don't like how this article has no examples with a terminal window or a code window where monospace gives a nice grid layout to the text


The actual website has an (interactive) editor window: https://monaspace.githubnext.com/


It is impressive and interesting, but I would suggest just using proportional fonts and stop caring about alignment.


>and stop caring about alignment.

absolutely impossible for me, so perhaps it has a use for likeminded folks.


I prefer being able to quickly recognize the specific characters and this would drive me nuts in a diff where same character can change. I am not a fan of this for coding.


It seems to me the problem with that font is that the strokes are way too thick, making the "m" look like it's almost all ink, and it also seems that the lowercase characters are far too tall for their width.

If you use a normal stroke width (one that makes the empty space in the "m" as wide as the stroke) and width/height ratio for all characters, the problem naturally disappears, and in fact this is not a problem for instance in Linux terminals with the default fonts (normally DejaVu Sans Mono), where the characters look perfectly natural and fine.


Tried it but honestly I like Iosevka too much. I love to split my code into-multiple side-by-side windows and Iosevka is perfect.


Makes sense that an entity as powerful as Github would like to make programming even more error prone than it already is. Gotta get that money!


Doesn't it defeat the purpose? If someone really wants this behavior, then why use monospace fonts in the first place?


The value here is to improve legibility of body copy, e.g. code, not headlines, where optical spacing rules change, so the example choice is odd. This definitely makes sense for programming, I would like to see this in Jet Brains Mono.


Please make all the digit glyphs the same width. It’s so retarded to see a (eg.) percent complete message jump around horizontally because it went from 11 to 12. I swear it’s a recent phenomena too… bar humbug.


Related:

Might as well be in this thread on the Monaspace fonts https://news.ycombinator.com/item?id=38210574


Isn't this just kerning but with extra steps?


It looks like it's also switching between variants of the same letter which are different widths, not just varying the space between characters.


Monospaced Kerning would be a better name than "Texture Healing".


Some MBA had a field day with this one.


It's more partial or constrained kerning (you can't leave your "box"), and then on top of that glyphs are being scaled at the same time to take up space "left over". In a proportional font it would just be kerned and the overall "footprint" changes.


With the difference that it keeps the font monospaced (in average), and usually kerning doesnt change shapes


Seeing the exact same character in a single word having two different sizes is way more infuriating to me than a classic monospaced font having "wide" i and "narrow" m. Maybe I'd get used to it over time but right now my eyes get hung up on the differences.


This is how I feel about English language where every 'e' in Mercedes is different.


I wonder if this could help the VGA like font in dosemu2.

It uses SDF and looks good, just not quite angular enough at bigger zooms for me.


this looks really nice except 0's often look super weirdly fat and out of place




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: