This document describes the patterns we are using to organize and write CSS for JupyterLab.
const
s and follow the CSS
class naming convention described below.index.css
.src/default-theme/variables.css
are used
to style plugins where ever possible.We are using native CSS variables in JupyterLab. This is to enable dynamic theming of built-in and third party plugins. As of Septmeber 2016, CSS variables are supported in the latest stable versions of all popular browsers, except for IE/Edge. If a JupyterLab deployment needs to support these browsers, a server side CSS preprocessor such as Myth or cssnext may be used.
We use the following convention for naming CSS variables:
--jp-
-
color
, font-size
or background
.--jp-notebook-cell-
.Some CSS variables in JupyterLab are considered part of our public API. Others are considered private and should not be used by third party plugins or themes. The difference between public and private variables is simple:
--jp-private-
private-
prefix are public.:root
pseudo-selector. This
ensures that public CSS variables can be inspected under the top-level
<html>
tag in the browser's dev tools.JupyterLab includes a default set of CSS variables in the file:
src/default-theme/variables.css
To ensure consistent design in JupyterLab, all built-in and third party
extensions should use these variables in their styles if at all possible.
Documentation about those variables can be found in the variables.css
file
itself.
Plugins are free to define additional public and private CSS variables in
their own index.css
file, but should do so sparingly.
We are organizing our CSS files in the following manner:
src
directory should contain
any CSS files needed to style itself.index.css
at the top-level of the plugin.index.css
of each plugin should be imported inside src/default-theme/index.css
.We have a fairly formal method for naming our CSS classes.
First, CSS class names are associated with TypeScript classes that extend
phosphor.Widget
:
The .node
of each such widget should have a CSS class that matches
the name of the TypeScript class, and those classnames should be defined
as a file-level const
:
const MYWIDGET_CLASS = 'jp-MyWidget';
class MyWidget extends Widget {
constructor() {
super();
this.addClass(MYWIDGET_CLASS);
}
}
Second, subclasses should have a CSS class for both the parent and child:
const MYWIDGET_SUBCLASS_CLASS = 'jp-MyWidgetSubclass';
class MyWidgetSubclass extends MyWidget {
constructor() {
super(); // Adds `jp-MyWidget`
this.addClass(MYWIDGET_SUBCLASS_CLASS);
}
}
Third, children nodes of a Widget
should have a third segment in the CSS
class name that gives a semantic naming of the component, such as:
jp-MyWidget-toolbar
jp-MyWidget-button
jp-MyWidget-contentButton
Thus, the general naming of CSS classes is of the form
jp-WidgetName-semanticChild
.
Fourth, some CSS classes are used to modify the state of a widget:
jp-mod-active
: applied to elements in the active statejp-mod-hover
: applied to elements in the hover statejp-mod-selected
: applied to elements while selectedFifth, some CSS classes are used to distinguish different types of a widget:
--jp-type-separator
: applied to menu items that are separators--jp-type-directory
: applied to elements in the file browser that are directories