A theme editor for JupyterLab
JupyterLab is a comprehensive web user interface for scientific and technical computing providing tools such as notebooks, text editors, consoles, and terminals. Like many similar tools, it allows users to choose from light or dark color themes. However, users may want to further adjust the looks of the interface, just for fun or for specific personal preferences or needs.
The ability to fine-tune contrast, color palettes, and fonts can be very useful for accessibility, an essential requirement for software to be usable by the whole community. There is an ongoing project-wide effort to improve accessibility in Jupyter. Choices of color palettes impact color-blind users while font choices can have a significant impact on people affected by dyslexia, or who suffer from migraines.
This diversity of requirements and preferences shows that end users should have the means to adjust parameters and tweak existing themes. Subtle differences can improve comfort significantly.
JupyterLab themes
Theming in JupyterLab is enabled by the fact that most of the layout and colors of the UI are defined by a set of CSS variables. There is no need for a complete stylesheet: one can set values for the base parameters from which the appearance of the user interface is derived. This system ensures a consistent look and feel throughout the application.
Custom themes provide a set of values for the base CSS variables and package the resulting CSS file in JupyterLab extensions. A search on GitHub returns 29 repositories defining such custom themes for JupyterLab.
Creating a theme requires implementing values for dozens of base CSS variables. This is often achieved by theme authors tweaking the values given in the default dark or light themes.
Generating a consistent palette, testing, and packaging the outcome in the form of a JupyterLab extension requires development skills and is neither direct nor trivial.
A new tool for authoring JupyterLab themes
To lower the bar for customizing JupyterLab we created a new tool providing a simple interface for tuning the JupyterLab appearance interactively, allowing theme authors to:
- use the selected colors in their application and “pin down” the result in the configuration,
- export the outcome in a form amenable to packaging into a new JupyterLab theme.
The theme editor extension is a theme prototyping tool, a sandbox to test changes in colors, font family and font size, and a configuration tool for end users. It displays a reduced set of parameters one can play with, allowing users to select:
- colors through color pickers,
- numerical values from sliders (for font size, border radius and width),
- font families from a predefined dropdown list.
A screenshot of JupyterLab with the theme editor panel is displayed in Figure 1, with a notebook opened in light theme. Figure 2 shows different screenshots with different custom themes.

Color palettes
For all the colors (accent, brand, border, error, info, layout, success, warn), the same logic is applied. The user picks a base color and a palette is automatically calculated using Microsoft’s fast-colors library.
Let’s take the specific example of the layout colors impacting the background of most elements of the interface. They are defined using — jp-layout-colori CSS variables from white to light grays (for the light theme).
- jp-layout-color0: white;
- jp-layout-color1: white;
- jp-layout-color2: var(-md-grey-200);
- jp-layout-color3: var(-md-grey-400);
- jp-layout-color4: var(-md-grey-600);
The number of colors in the palette fits the number of colors in the CSS set of variables (here the palette contains 5 colors). There are different ways to define colors (hexadecimal, RGBA, HSLA). The latter format has the advantage of giving direct access to luminance L, a measure of the lightness of a given color.
An inverse layout palette is computed for use with most text elements. The luminance of the inverse layout color L’ is calculated as 1-L plus a correction depending on how 1-L is close to 0.5. There isn’t a general CSS rule in JupyterLab concerning elements on top of a background but some PRs were proposed to reinforce the coupling between inverse layout elements and layout backgrounds with the same color index. The contrast still needs to be improved though, by using other palettes or better corrections when defining the inverse layout colors.
The full process just described from picking a layout color to resulting palettes and the corresponding interface is illustrated in Figure 3.

Font size and font family
As mentioned previously, font size and font family can be tuned too. Let’s take the example of the — jp-ui-font-size[i] CSS variables defining the text size of most of the text elements in the interface:
- jp-ui-font-scale-factor: 1.2;
- jp-ui-font-size0: 0.8333em;
- jp-ui-font-size1: 13px; /* Base font size */
- jp-ui-font-size2: 1.2em;
- jp-ui-font-size3: 1.44em;
A slider lets the user control the base font size associated with — jp-ui-font-size1. The other font sizes are then calculated by applying a scale factor to the base font.
Concerning font families, a non-exhaustive list is proposed (i.e., default browser fonts or Google fonts). It includes both standard accessible fonts (Arial, Courier, Helvetica, Sans Serif, system-ui, Times New Roman, Verdana) and less usual ones to create artistic or special interfaces with cursive fonts ( for instance Dancing Script or Single Day). Only 2 fonts are proposed for code: Space Mono and monospace.
Storing the new theme
Once satisfied with a new theme, users can export it using a button at the top of the theme editor panel. This creates a variable.css file that can be packaged in a theme extension (see the extension template). The new parameters are also synchronously saved in the settings editor and can be restored for the next JupyterLab opening if the boolean useSettings is set to true. If not, the interface will look like in Figure 1: with light theme default CSS values. Resetting useSettings to true will restore the formerly tuned parameters.
Future development
The look and feel of the theme editor UI still needs to be improved. We will work on unifying the styling of all interfaces making use of react-jsonschema-form. It is already used for the JupyterLab settings editor, the notebook metadata editor of JupyterLab 4.0, and several extensions.
Moreover, the current implementation is bound to fast-colors palettes and we may want to use a different approach, like decoupling the layout and inverse layout palettes to reach better contrasts or give more freedom in the color choices.
Any help (e.g., filling issues for bugs or enhancement requests, opening pull requests) to improve the extension is welcome.
Try it out
You can install the PyPI package by running:
pip install jupyter_theme_editor
You can also try the theme editor on Binder.
Aknowledgement
Many thanks to Isabel Paredes for drawing the palette icon!
About the authors
Florence Haudin is a scientific software developer at QuantStack. She contributes to JupyterLab and to ipyleaflet.
Frédéric Collonval supervised this work as a technical director at QuantStack. He is a member of the JupyterLab core team and authored several JupyterLab extensions.