-
Notifications
You must be signed in to change notification settings - Fork 73
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 all neovim users, though more likely newer ones, to solve issues related to missing or bad looking icons in terminals. If you just want to unblock yourself and already know all you want to about fonts and rendering then focus on the Troubleshooting section. Otherwise I encourage you to checkout some of the other sections as well.
This is an early version and will be updated based on feedback.
In order to use the tables below you need to know 3 pieces of information:
- What problem you are facing with icons. Possible values are:
- Missing �: Icons are either clearly wrong or missing and being shown as a �.
- Too Small: Icons are smaller than you want and are hard to see.
- Too Large: Icons are larger than you want and look squished.
- The terminal emulator you are using for neovim. Currently we have info for:
- The type of font you are using. Possible values are:
- Nerd Normal: Standard Nerd Font, the name ends with "Nerd Font". For example "JetBrainsMono Nerd Font".
- Nerd Mono: Monospaced symbol variant of a Nerd Font, the name ends with "Nerd Font Mono". For example "JetBrainsMono Nerd Font Mono". Notice the second "Mono", that is the important part.
- Base: Any font that is not a Nerd Font. Probably the case if you have not configured a font for your terminal emulator.
If your situation is not covered by these please reach out!
Once you know all that, you can get to the solution. Use the table associated with your problem and go from there. Examples:
- Missing � + Alacritty + Nerd Normal = ✅ Font -> Nerd
- Too Small + WezTerm + Base = ✅ Wez Glyphs Grow
- Too Large + kitty + Nerd Mono = ✅ Font -> Base
This process can be iterative where after making a change you still do not like the output. Continue from the top each time but make sure to update your situation based on any changes you've made.
Terminal / Font | Base | Nerd Normal | Nerd Mono |
---|---|---|---|
WezTerm | ❓ Always Find | ❓ Always Find | ❓ Always Find |
kitty | ❓ Always Find | ❓ Always Find | ❓ Always Find |
Alacritty | ✅ Font -> Nerd | ✅ Font -> Nerd | ✅ Font -> Nerd |
- ✅ = Potential Fix
- ❌ = No Fix
- ❓ = Impossible
Terminal / Font | Base | Nerd Normal | Nerd Mono |
---|---|---|---|
WezTerm | ✅ Wez Glyphs Grow | ✅ Font -> Base | ✅ Font -> Base |
kitty | ✅ Kitty Symbols Normal | ✅ Font -> Base | ✅ Font -> Base |
Alacritty | ❓ Never Find | ❌ Size Limit | ✅ Font Variant |
- ✅ = Potential Fix
- ❌ = No Fix
- ❓ = Impossible
Terminal / Font | Base | Nerd Normal | Nerd Mono |
---|---|---|---|
WezTerm | ✅ Wez Glyphs Shrink | ✅ Font -> Base | ✅ Font -> Base |
kitty | ✅ Kitty Symbols Mono | ✅ Font -> Base | ✅ Font -> Base |
Alacritty | ❓ Never Find | ✅ Font Variant | ❌ Size Limit |
- ✅ = Potential Fix
- ❌ = No Fix
- ❓ = Impossible
There are 2 levers we can pull to Grow or Shrink icons:
- Overflow
- Controlled by: allow_square_glyphs_to_overflow_width
- Whether icons are allowed to expand outside of their cells
- Scaling
- Controlled by: font_with_fallback scale
- A factor by which icons are transformed before being displayed
To Grow icons enable overflow:
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 option, you can also set it explicitly if you like.
To Shrink icons disable overflow:
config.allow_square_glyphs_to_overflow_width = 'Never'
At this point update the config, save, and check the size of the icons to see if you like the result. If you do, then you're done.
Otherwise try scaling, replace the <scale>
placeholder with:
- Grow: a value > 1.0, start with 1.1 and adjust from there
- Shrink: a value < 1.0, start with 0.9 and adjust from there
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 Normal Nerd Font or a Mono Nerd Font as specified.
Your situation:
- Terminal emulator: supports Font Fallback
- Font: some Nerd Font
- Problem: icons render but don't look great
Using a Nerd Font when the terminal emulator supports fallback is unnecessary since the fallback should handle all icons without a Nerd Font. It is also discouraged, see Patched Nerd Fonts.
Before working on anything related to how icons look the first thing to do is change the terminal emulator font to any Base Font. This means any font so long as it is not a Nerd Font, give Comic Sans a try. You can install a new font if you want as long as it is not a Nerd Font. The name should not contain "Nerd Font".
The goal is to have the terminal emulator resolve icons for you using the fallback mechanism rather than using icons that are part of your main font. This will give more control over changing how icons are displayed as well.
This will likely change how the icons look and could fix the problem on its own.
Your situation:
- Terminal emulator: does not support Font Fallback
- Font: N/A
- Problem: icons are missing
Missing icons mean that they are missing from the font you are using. The fix is to find a font that supports them and use that as your terminal emulator font.
If you're not using a Nerd Font then you'll need to start using one. If you're already using a Nerd Font then you'll need to try other ones since it is not the case that all Nerd Fonts contain all icons.
Follow these steps which will install multiple variants of your chosen Nerd Font. When picking a variant feel free to use any of them. Different variants will contain all the same icons but will be rendered differently.
Your situation:
- Terminal emulator: does not support Font Fallback
- Font: some Nerd Font
- Problem: icon size
Different Nerd Font variants have different sized icons:
- Normal: has larger icons, example "JetBrainsMono Nerd Font"
- Mono: has smaller icons, example "JetBrainsMono Nerd Font Mono"
It is likely when you installed your Nerd Font it came with both variants so the fix is to swap the variant your terminal emulator is using.
- Normal -> Mono means your icons should get smaller
- Mono -> Normal means your icons should get larger
If your font did not come with the other variant for some reason, you'll need to find and download it, or try a new Nerd Font.
Your situation:
- Terminal emulator: supports Font Fallback
- Font: N/A
- Problem: icons are missing
This is unexpected since any icons not supported by your font should be handled by the fallback which searches through system and bundled fonts to see if any can render the icon. If you encounter this let me know!
Your situation:
- Terminal emulator: does not support Font Fallback
- Font: some Base Font
- Problem: icons render but don't look great
This is an unexpected situation since non Nerd Fonts should be missing all the niche icons and result in some default being rendered, such as �. If you encounter this let me know!
When a Nerd Font is created from a Base Font the author typically creates multiple variants. We've labelled these as Nerd Normal and Nerd Mono, below is a comparison.
Nerd Normal | Nerd Mono | |
---|---|---|
Icon Width | Double | Single |
Icon Size | Larger | Smaller |
Monospaced? | ❌ | ✅ |
Some terminal emulators can use the larger icons from Nerd Normal when there is space.
A consequence of the above is that if you're using the Normal variant you cannot get bigger icons. Similarly if you're using the Mono variant you cannot get smaller icons. If you find an exception or there is a way around this let me know!
- I found that for
SymbolsNerdFont
this is not the case and the Mono variant is larger than the Normal variant, but this seems like an exception?
- Download a Nerd Font: A popular one is
JetBrainsMono Nerd Font
but any of them should work, pick the one you like. You can do this using: - Install the Nerd Font: 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. - Use the Nerd Font: Set the font as your terminal emulator's font. How depends
on the terminal emulator, could be under a settings panel, or a configuration
file. A search for " font config" should get you there.
- After installing the font you'll have multiple variants available, such as
JetBrainsMono Nerd Font
andJetBrainsMono Nerd Font Mono
. Use the correct one if specified, otherwise the former is usually a safe choice.
- After installing the font you'll have multiple variants available, such as
So you 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 try an awesome markdown renderer :) and you notice the dreaded �, what's going on?
Well, like many people, up until now you only needed your terminal to display letters, numbers, and basic symbols you find on your keyboard. So your font, which likely only implements these basic characters wasn't a problem. Now you want to display complex icons / glyphs which leads to this problem. When your font doesn't implement a particular icon your terminal emulator (WezTerm, kitty, Alacritty, iTerm2, etc.) won't know how to display it. As a last resort it will pickup some default icon that it can render, like �, and show that to you. At this point might have some questions, it's a good time to browse the FAQs before moving on.
TODO
How text is rendered by your terminal emulator depends on the 2 things you would expect, the font and the terminal emulator itself. What text can be rendered depends on these same 2 things.
The burden of who needs to provide all the necessary icons results in 2 distinct approaches. If the font does the heavy lifting we end up with "Patched Nerd Fonts" and if the terminal emulator does we end up with font fallback. I'll briefly touch on the former and explain why it may still be your only viable option first.
Patched Nerd 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
which is managed and distributed
completely separately from the Base Font. These also will typically come with different
variants of the same font like a version with monospaced icons (by default icons
are double width) named JetBrainsMono Nerd Font Mono
.
By offloading this effort to the font the terminal emulator can avoid any complexity in handling missing icons. Instead either the configured font has the icon and we use it or we fallback to a default and move on. This also avoid any merging and mangling of multiple fonts, glorious simplicity.
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. I would not go so far but if you are able to avoid using them then that will likely lead to a more consistent experience for you. However sometimes you just can't, and if there is no alternative, like a mandatory terminal emulator you need to use for work that doesn't implement font fallback then Patched Nerd Fonts are really your only option, and they're not even a bad one.
Now for the more complex alternative of terminal emulators that build out font fallback and as a result avoid the need for users to use Patched Nerd Fonts. Below is a table of those that implement the feature:
Terminal | Font Fallback |
---|---|
WezTerm | ✅ |
kitty | ✅ |
Alacritty | ❌ |
The way this works at a high level is fairly simple to understand. Sure, your main font may not have some icon, but maybe some other font on your system does. Better yet even if no font on your system does there's nothing stopping us from bundling fonts directly into the terminal emulator as a fallback in case all else fails. Now the complexity of joining glyphs from separate fonts and making it look cohesive is not trivial, but once the work is done you end up with an incredibly robust font rendering experience. Many such terminal emulators will bundle a "symbols only" font which is just the icons from nerd fonts without the standard letters / numbers, those are provided by your preferred font. This means you don't need wait for a Patched version of your favorite font to be created. Instead you can use any font you want, yes, including Comic Sans, and any missing symbols get filled in by the terminal emulator on the fly, awesome!
How the fallback works will depend on the terminal emulator's implementation. If you are using a supported terminal emulator then in theory you should never see a � ever. It is highly recommended to avoid Patched Nerd Fonts when using these terminal emulators since the fallback only kicks in if your font is missing an icon. This will typically result in a more configurable and cohesive experience, especially if the terminal emulator gives you control of how the fallback works.
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 of them 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 largely a grid where we can paint some pixels in each cell. We've essentially taken some UTF-8 encodings and mapped them to cool looking icons using the power of fonts.
Well maybe not directly, but some plugin you're using probably 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 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 not possible in any terminal emulator that I am aware of. I'm not really sure where the fundamental limitation is. Terminals have been grids since their inception, but in theory this is not mandatory. Though I do not believe there are any ANSI sequences that exist that would allow text size information to be communicated to the terminal emulator. Maybe one day ANSI sequences will be added, terminals will be updated, and clients like neovim will add support, or maybe there's more challenges involved, or maybe it's not that important. In any case for now this doesn't exist.