-
Notifications
You must be signed in to change notification settings - Fork 61
Fonts
I am no expert on font rendering and some of the details below are likely oversimplified. If you find anything to be inaccurate or misleading please let me know!
The goal is to provide a quick reference to neovim users new and old to solve issues related to missing or bad looking icons in terminals. This is an early version and will be updated based on feedback.
If you just want a way to unblock yourself and already know all you care to about font rendering then focus on the Troubleshooting section. Otherwise I encourage you to checkout some of the other sections with more details.
In order to use the table below you need to know 3 pieces of information:
- The terminal emulator you are using for neovim. Currently we support:
- The type of Nerd Font you are using. Possible values are:
- Regular: This is if you're using a standard Nerd Font. This is true if the name ends with "Nerd Font", for example "JetBrainsMono Nerd Font".
- Mono: Similar to above, but the monospaced symbol variant. This is true if the name ends with "Nerd Font Mono", for example "JetBrainsMono Nerd Font Mono". Notice the second "Mono", that is the important part.
- Non: This is the case if you're not not using any kind of Nerd Font, essentially true if no other option is, probably the case if you have not configured a font.
- What problem you are facing with the icons. Possible values are:
- Missing �: Icons are either clearly wrong or missing and being shown as a �.
- Too Small: Icons are rendered smaller than you want and are hard to see.
- Too Large: Icons are rendered larger than you want and look squished.
If your specific problem is not covered by any of these please reach out!
Once you have all that you can get to the solution. For example kitty + Mono + Too Large links me to the Change Font to Non Nerd section.
Legend:
- ✅ = Potential Fix
- ❌ = No Fix
- ❓ = Impossible
There are 2 levers we can pull to grow or shrink icons.
The first lever is through allow_square_glyphs_to_overflow_width.
To grow icons you'll need to allow them to overflow their cells:
config.allow_square_glyphs_to_overflow_width = 'WhenFollowedBySpace'
- This is the default value so this is more of a sanity check that you did not disable this, but you can also set it explicitly if you like.
To shrink icons you'll need to prevent them from overflowing their cells:
config.allow_square_glyphs_to_overflow_width = 'Never'
At this point you can update the config, save, and check the size of the icons to see if you're happy with it. If you are then nothing else is needed.
Otherwise use the second lever through font_with_fallback scale.
In the example below you can replace the <scale>
placeholder with a value > 1
(like 1.10) to grow icons or a value < 1 (like 0.90) to shrink icons.
config.font = wezterm.font_with_fallback({
{ family = '<your_current_font>' },
{ family = 'Symbols Nerd Font Mono', scale = <scale> },
})
Set the font for the symbol_map
described here
to either a Regular Nerd Font or a Nerd Font Mono as defined in the solution.
The advice is to change the terminal emulator font to any Non Nerd Font (does not contain the string "Nerd Font") on your system, even Comic Sans. You can install a new font if you like but that is not necessary. The goal is to have the terminal emulator resolve symbols for you using its fallback logic.
Follow these steps which fill install multiple variants of your chosen nerd font. When you go to pick a variant for your terminal emulator choose any of them.
Follow these steps but make sure the font you install is different from the one you are currently using. This is to make it likely that the new font will cover icons the previous one did not.
Follow these steps which fill install multiple variants of your chosen nerd font. When you go to pick a variant for your terminal emulator make sure you select the font that ends with "Nerd Font".
Follow these steps which fill install multiple variants of your chosen nerd font. When you go to pick a variant for your terminal emulator make sure you select the font that ends with "Nerd Font Mono".
Some terminal emulators, particularly newer ones, have the ability to search through more than just your default font. If a particular icon is missing it will trigger fallback logic which will search through system fonts as well as fonts that come bundled with the terminal emulator by the author. This should prevent any icons from being missing, so if you encounter this let me know!
This is the converse of the "Should Always Find" problem. If a terminal emulator does not support font fallback and you are not using a Nerd Font of some sort it would be completely unexpected for any symbols to render in any way other the �, so if you encounter this let me know!
When Nerd Fonts are created from their base fonts the authors create multiple variants. We've talked about these before as Regular and Mono. The difference between these is that the Regular variant has double width icons which some terminal emulators can take advantage of when space allows. Mono on the other hand has single width icons which makes the entire font (both base and icons) monospaced.
As a result if you're already using the Regular variant you cannot get bigger icons.
Similarly if you're using the Mono variant you cannot get smaller icons.
If you find this to not be the case and their is a way around this issue let me know!
A popular one is JetBrainsMono Nerd Font
but any of them should work, pick the
one you like. You can do this using:
This depends on your OS and could involve moving a file to a specific directory,
running some command, or is already handled by your package manager like with homebrew
.
You just need the font to be visible, Google / LLM should help here.
Set the font as your terminal emulator's font. How depends on the exact terminal emulator and could be under a settings panel or done through a configuration file. A search for " font config" should get you there.
This section covers some of the high level details about why we use icons and why they don't always work out of the box.
So you've downloaded neovim and picked up a few plugins, nice! Then you open up your new file tree from neo-tree.nvim or take a look at your status line from lualine.nvim or an awesome markdown renderer :) and you notice the dreaded �, what's going on?
Well, like most people, up until now, you've only ever needed your terminal to display letters, numbers, and the basic symbols you find on your keyboard. So your font, which likely only implements these basic characters was never a problem. Now you want to display complex glyphs / icons, leading to this problem. When your font doesn't implement a particular icon, your terminal emulator (WezTerm, kitty, Alacritty, iTerm2, etc.) doesn't know what to do, so as a last resort will show you the �. At this point might have some questions, it's a good time to browse the FAQs to see if they're covered before moving on.
How fonts are rendered by your terminal emulator depends on the 2 things you would expect, the font and the terminal emulator. This means the same font used by different terminal emulators will look different. Think of this as the font providing the raw data and the terminal emulator using the data to create an image. We'll cover these 2 sides separately.
When we talk about fonts that includes many niche icons we're typically talking about "patched nerd fonts".
These fonts are generated by taking some existing base font, like JetBrains Mono
,
and filling all the "gaps" with a set of common icons. This creates a new font with
a name like JetBrainsMono Nerd Font
, this kind of naming convention is used for
most patched nerd fonts. These will typically come with different variants of the
same font like a version with monospaced icons (by default the icons are wider) which
will be called JetBrainsMono Nerd Font Mono
.
You may come across information saying you should not use these fonts and they're "bad practice" or "harmful". These are opinions with some legitimate reasons behind them. My stance, that you will need to read further to understand, is that if you can avoid using a patched nerd font then you should not use one. However, there are situations where there are no other options and they are the only solution.
You may be wondering, well if these fonts are "bad" then what do I use, there doesn't even seem to be an alternative. This is where we get into the terminal emulator side.
In the most basic case you set a font for your terminal emulator, it looks up some UTF-8 to get information on how to render a character and if it's missing then you get some default output like �. If this is the case for your terminal emulator then you need to use a patched nerd font to get icons, there is no alternative.
However many terminal emulators, especially more recent ones, can take advantage of multiple fonts using what is called font fallback. Essentially you set a preferred font, and if an icon is missing, rather than giving up, the terminal emulator will go through some process to look at other available fonts and find one that does know how to render the icon. Available fonts can mean fonts on your system but also fonts that are bundled with the terminal emulator directly by the author. For these terminal emulators they will often come with a "symbols only" font which is just the icons and non of the standard letters / numbers, instead those are provided by your preferred font, which can now be anything, including Comic Sans. How the fallback works depends on the terminal emulator's implementation.
Terminal | Font Fallback |
---|---|
WezTerm | ✅ |
kitty | ✅ |
Alacritty | ❌ |
If you are using a supported terminal emulator then in theory you should never see a �. You should also avoid using patched nerd fonts and instead use the base font directly and allow the fallback to handle symbols. The reason to not use a patched font is that, as far as I know, letting the terminal emulator handles this leads to more consistent behaviors, i.e. icons all being pulled from a single font.
This is a very niche problem that most fonts don't need to solve. These missing icons are most likely what are referred to as nerd font icons, and there are over 10,000 of them.
The idea of every font shipping with implementations for all these icons is crazy if you think about it. Who out there using Comic Sans in Word is trying to inline the GitHub logo as text? If font authors went through the trouble of making unique icons it would be an insane amount of work for a small portion of users. If they shared the same icons and kept the font part unique all fonts would get much bigger. Maybe not much of a problem now but still wasteful and extra effort.
GUI applications do not come with the same set of limitations as a terminal. They can render an image no problem. Terminals on the other hand are a fixed size grid where we can paint some pixels in each cell. We've essentially taken some UTF-8 encodings and mapped them to icons using the power fonts.
Well maybe not directly, but some plugin you're using did. Somewhere in the code for the plugin you'll find the UTF-8 encoded character that represents the icon your font is missing.
You're technically correct, we do it for the aesthetic :P I'll add that icons, when used effectively, can give you a lot of information at a glance. With file trees for instance they will tell you what's a folder and the type of each file, once you know what you're looking at. It's likely a bit of both and it's totally reasonable to want things to look nice in an environment you spend hours a day in.
The purist may disagree, and the purist is free to use something else or write it themselves.
No, this is just not possible in any terminal emulator. The grid base of all terminal emulators relies on fixed size cells. If you make a font larger it gets taller and wider meaning the cells become different sizes and you no longer have a grid.