I've replaced Source Code Pro with a variant of Iosevka
as the monospace font for my blog theme! While Source
Code Pro is available on Google Fonts and could be included
from there with a single line of code, Iosevka wasn't, so a bit more work was needed.
I've been a fan of Iosevka and using it as my coding font since the day I first saw it appear on Hacker News. It's noticeably narrower than most monospace fonts, but that was a part of its appeal for me—at the very least, you can fit more code into the horizontal space on your screen.
Here's some Haskell code from my solution for Advent of Code 2015 day 22:
cast :: Spell -> GameState -> GameState
cast spell state = case spell of MISSILE -> castMissile state
DRAIN -> castDrain state
SHIELD -> castShield state
POISON -> castPoison state
RECHARGE -> castRecharge state
Iosevka is a highly customisable font. Besides the multiple pre-built variants you can download from its GitHub
releases, you can also build it from source to exercise full control
over the many available customisation options. These range from options that affect the overall look and feel such
as ligations, serifs and spacing, to those that change how individual characters look—whether you want a double-
or single-storey a
and g
, whether the middle leg of the letter m
should be shorter than the other two or
whether the number 3
should have a flat top.
You can see a visual representation of all the available styles and customisation options at the Iosevka GitHub repository:
be5invis/IosevkaSlender typeface for code, from code.https://github.com/be5invis/Iosevka
Building Iosevka
Besides customisation, Iosevka also has to be built from source to get the woff
and woff2
web font formats.
Dependencies
Building Iosevka requires a handful of dependencies. On my platform (Ubuntu 16.04 on WSL), some of these were available from package management or as binary downloads, while the rest had to be built from source.
node
—installed usingnvm
.ttfautohint
—installed throughapt-get
.otfcc
—built from source from caryl/otfcc. Requiredpremake5
to build, which could be downloaded as a prebuilt binary from here.sfnt2woff
—installed throughapt-get
from thewoff-tools
package.woff2_compress
—built from source from google/woff2.
After ensuring all the dependences have been added to your $PATH
, clone the Iosevka repository, check out the
latest release (v1.14.3
at time of writing) and install Node dependencies with npm install
or yarn
.
Customisation
Building a custom variant of Iosevka involves two separate Makefile targets. make custom-config
will generate
a configuration file which will be used by make custom
or make custom-web
to build the actual font files.
Since I was building the ss05
(Fira Mono style) preset of Iosevka v1.14.3
, I specified set=ss05-1.14.3
. I
also only needed the book (regular) and bold weights:
make custom-config set=ss05-1.14.3 design=ss05 weights='book bold'
make custom-web set=ss05-1.14.3
This populates the dist/iosevka-ss05-1.14.3/
directory:
$ tree dist/iosevka-ss05-1.14.3/
dist/iosevka-ss05-1.14.3/
├── ttf
│ ├── iosevka-ss05-1.14.3-bolditalic.ttf
│ ├── iosevka-ss05-1.14.3-boldoblique.ttf
│ ├── iosevka-ss05-1.14.3-bold.ttf
│ ├── iosevka-ss05-1.14.3-italic.ttf
│ ├── iosevka-ss05-1.14.3-oblique.ttf
│ └── iosevka-ss05-1.14.3-regular.ttf
├── woff
│ ├── iosevka-ss05-1.14.3-bolditalic.woff
│ ├── iosevka-ss05-1.14.3-boldoblique.woff
│ ├── iosevka-ss05-1.14.3-bold.woff
│ ├── iosevka-ss05-1.14.3-italic.woff
│ ├── iosevka-ss05-1.14.3-oblique.woff
│ └── iosevka-ss05-1.14.3-regular.woff
└── woff2
├── iosevka-ss05-1.14.3-bolditalic.woff2
├── iosevka-ss05-1.14.3-boldoblique.woff2
├── iosevka-ss05-1.14.3-bold.woff2
├── iosevka-ss05-1.14.3-italic.woff2
├── iosevka-ss05-1.14.3-oblique.woff2
└── iosevka-ss05-1.14.3-regular.woff2
3 directories, 18 files
$
Serving web fonts
The line of code you add from Google Fonts loads a CSS stylesheet which tells browsers where to find the fonts you'll be using.
For example, including two different weights of Source Code Pro from Google Fonts will load this piece of CSS1 from here:
/* latin-ext */
@font-face {
font-family: 'Source Code Pro';
font-style: normal;
font-weight: 400;
src: local('Source Code Pro'), local('SourceCodePro-Regular'), url(https://fonts.gstatic.com/s/sourcecodepro/v7/HI_SiYsKILxRpg3hIP6sJ7fM7PqlM-vWjMY.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Source Code Pro';
font-style: normal;
font-weight: 400;
src: local('Source Code Pro'), local('SourceCodePro-Regular'), url(https://fonts.gstatic.com/s/sourcecodepro/v7/HI_SiYsKILxRpg3hIP6sJ7fM7PqlPevW.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@font-face {
font-family: 'Source Code Pro';
font-style: normal;
font-weight: 700;
src: local('Source Code Pro Bold'), local('SourceCodePro-Bold'), url(https://fonts.gstatic.com/s/sourcecodepro/v7/HI_XiYsKILxRpg3hIP6sJ7fM7Pqths7Dvecq_mk.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Source Code Pro';
font-style: normal;
font-weight: 700;
src: local('Source Code Pro Bold'), local('SourceCodePro-Bold'), url(https://fonts.gstatic.com/s/sourcecodepro/v7/HI_XiYsKILxRpg3hIP6sJ7fM7Pqths7Ds-cq.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
Each @font-face
block specifies, for a specific font family, style and weight, where to load the font from. The
local()
function tries to load a font installed locally on the machine, while the url()
points to where it
can be downloaded from online, and in what format.
Some other useful attributes for further optimising font delivery are font-display
, which determines how long
to wait for a font to load or whether to replace it with another font instead, and unicode-range
as seen above,
which specifies exactly which characters to be displayed in a particular font.
Loading our own fonts
To serve our own web fonts locally, we just need to include our own @font-face
declarations which point to our
locally hosted font files.
I only planned to need two different styles, normal 400 for most places and a bold version for headings. Building
Iosevka for web generated woff2
, woff
and ttf
versions, so I included them all:
@@font-face {
font-family: 'Iosevka';
font-style: normal;
font-weight: 400;
src: url('/fonts/iosevka-ss05-1.14.3-regular.woff2') format('woff2'), url('/fonts/iosevka-ss05-1.14.3-regular.woff') format('woff'), url('/fonts/iosevka-ss05-1.14.3-regular.ttf') format('truetype');
}
@font-face {
font-family: 'Iosevka';
font-style: normal;
font-weight: 700;
src: url('/fonts/iosevka-ss05-1.14.3-bold.woff2') format('woff2'), url('/fonts/iosevka-ss05-1.14.3-bold.woff') format('woff'), url('/fonts/iosevka-ss05-1.14.3-bold.ttf') format('truetype');
}
(I chose to include the version number in the path to hopefully avoid issues with caching when I decided to update to a newer version of Iosevka.)
Afterwards, just load your own @font-face
declarations as you would any other CSS. I included it in its own
CSS file and included it with:
<link rel="stylesheet" href="/css/iosevka.css">
Further reading
I found this article by Twitter engineer Mike Solomon to be very informative both while setting things up myself and writing this post afterwards:
Host your own web fontsMike Solomonhttps://msol.io/blog/tech/host-your-own-web-fonts/
-
According to CSS-Tricks, Google Fonts is pretty fancy and does things like varying the exact contents of the loaded CSS depending on browser. For example,
woff2
is a relatively new format andwoff2
URLs may not be included when requested by an older browser which doesn't support it. ↩︎