Jupyterlab-fonts: data-driven style and typography for JupyterLab



Hey folks! We just did a 2.0.0 release (finally) of jupyterlab-fonts that works with JupyterLab 3 on pypi and npm… conda-forge is coming soon :tada:.

What’s it look like?


JupyterLab themes are great, but you have to maintain them.

JupyterLab 3 natively supports using already-installed fonts and tuning a few parameters.


This extension ships a powerful toolbelt of style features so you can tune a Binder or JupyterLite to look just the way you want, either globally, or in a specific notebook.

The fonts it ships with today are:

Privacy/Performance note: fonts are fun, but heavy. While we can’t do much about performance, if those fonts aren’t enough, you can help privacy by sourcing third-party fonts from wikimedia’s CDN instead of Mountain View.

In addition, it offers line height and font size for the code and content fonts. With Advanced Settings or the Property Inspector, one can go crazy and do just about anything!


Under the hood, it uses the JSON-compatible parts of JSS (and its official plugins). A favorite is the nesting plugin, which lets you more simply specify complicated styles: this is great for modal things like single-document mode and presentation mode. You still have to understand CSS selectors, etc. but JSON fails much more loudly than CSS when something inevitably gets broken.

Where to next?

The next plan (probably a 2.1.0) is to reuse the underlying machinery to make a flexible, composable Jupyter widget and MIME renderer which will allow for precise styling of many of the deep parts of individual widgets and outputs which are sometimes hard-coded for the general use case, but not so much fun for really custom apps. Kind of like the Box classes, this will take the form of something like:

btn = Button(icon="star")
slider = StyleFloatSlider(unit="px")
box = HBox([btn, slider])
display(box)  # would show the "plain" box
style = Style(
    value={".jupyter-button": {"& i.fa": {"font-size": slider}}}
display(style) # would connect the "pretties"

The MIME renderer would be similar, and support some concept of scope (since it will draw in exactly one place).

Previously, it contained an nbconvert.Preprocesser… while this was fun, and I used it a bit, it didn’t work on nbviewer, etc. Hopefully the MIME-based approach will step up into this role!

Have fun making the pretties!