docs/source/developer/css.md
% Copyright (c) Jupyter Development Team.
% Distributed under the terms of the Modified BSD License.
(css)=
This document describes the patterns we are using to organize and write
CSS for JupyterLab. JupyterLab is developed using a set of npm packages
that are located in packages. Each of these packages has its own
style, but depend on CSS variables defined in a main theme package.
consts, but we are moving away from that.style
subdirectory and imported into the plugin's index.css.theme-light-extension
and theme-dark-extension packages are used to style packages
wherever possible. Individual packages should not npm-depend on
these packages though, to enable the theme to be swapped out.We are using native CSS variables in JupyterLab. This is to enable dynamic theming of built-in and third party plugins. As of December 2017, CSS variables are supported in the latest stable versions of all popular browsers, except for IE. 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-.-.--jp-notebook-cell-.active, not-active or focused:
--jp-notebook-cell-focused.color, font-size or background:
--jp-notebook-cell-focused-background.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.:root.JupyterLab includes a default set of CSS variables in the file packages/theme-light-extension/style/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.
Again, we consider the names of the public CSS variables in this package to be our public API for CSS.
We are organizing our CSS files in the following manner:
packages directory should contain
any CSS files in a style subdirectory that are needed to style
itself.style/base.css file.index.css file is templated by buildutils as
part of the integrity script. It imports the CSS in dependency order,
ending with the local ./base.css. CSS from external libraries is
determined by their style field in package.json. If additional
files are desired or the external library does not have a style field,
we use the jupyterlab: { "extraStyles": { "fooLibrary": ["path/to/css"] } }
pattern in our package.json to declare them.
For imports that should not be added to index.css, update SKIP_CSS in buildutils/src/ensure-repo.ts.We have a fairly formal method for naming our CSS classes.
First, CSS class names are associated with TypeScript classes that
extend lumino.Widget:
The .node of each such widget should have a CSS class that matches
the name of the TypeScript class:
class MyWidget extends Widget {
constructor() {
super();
this.addClass('jp-MyWidget');
}
}
Second, subclasses should have a CSS class for both the parent and child:
class MyWidgetSubclass extends MyWidget {
constructor() {
super(); // Adds `jp-MyWidget`
this.addClass('jp-MyWidgetSubclass');
}
}
In both of these cases, CSS class names with caps-case are reserved for
situations where there is a named TypeScript Widget subclass. These
classes are a way of a TypeScript class providing a public API for
styling.
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-toolbarjp-MyWidget-buttonjp-MyWidget-contentButtonIn general, the parent MyWidget should add these classes to the
children. This applies when the children are plain DOM nodes or
Widget instances/subclasses themselves. Thus, the general naming of
CSS classes is of the form jp-WidgetName-semanticChild. This enables
the styling of these children in a manner that is independent of the
children implementation or CSS classes they have themselves.
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 separatorsjp-type-directory: applied to elements in the file browser that
are directoriesOver time, we have found that there are some edge cases that these rules don't fully address. Here, we try to clarify those edge cases.
When should a parent add a class to children?
Above, we state that a parent (MyWidget), should add CSS classes to
children that indicate the semantic function of the child. Thus, the
MyWidget subclass of Widget should add jp-MyWidget to itself
and jp-MyWidget-toolbar to a toolbar child.
What if the child itself is a Widget and already has a proper CSS
class name itself, such as jp-Toolbar? Why not use selectors such as
.jp-MyWidget .jp-Toolbar or .jp-MyWidget > .jp-Toolbar?
The reason is that these selectors are dependent on the implementation
of the toolbar having the jp-Toolbar CSS class. When MyWidget
adds the jp-MyWidget-toolbar class, it can style the child
independent of its implementation. The other reason to add the
jp-MyWidget-toolbar class is if the DOM structure is highly
recursive, the usual descendant selectors may not be specific to target
only the desired children.
When in doubt, there is little harm done in parents adding selectors to children.
(css-selectors)=
We use CSS selectors to decide which context menu items to display and what command to invoke when a keyboard shortcut is used. The following common CSS selectors are intended to be used for adding context menu items and keyboard shortcuts.
CSS classes that target widgets and their children
jp-Activity: applied to elements in the main work areajp-Cell: applied to cellsjp-CodeCell: applied to code cellsjp-CodeConsole: applied to consolesjp-CodeConsole-content: applied to content panels in consolesjp-CodeConsole-promptCell: applied to active prompt cells in consolesjp-DirListing-content: applied to contents of file browser directory listingsjp-DirListing-item: applied to items in file browser directory listingsjp-FileEditor: applied to file editorsjp-ImageViewer: applied to image viewersjp-InputArea-editor: applied to cell input area editorsjp-Notebook: applied to notebooksjp-SettingEditor: applied to setting editorsjp-SideBar: applied to sidebarsjp-Terminal: applied to terminalsjp-zoom-target: applied to the element within a widget that should respond to zoom actions. Extensions can add this class to define where per-widget zoom should be applied.CSS classes that describe the state of a widget
jp-mod-current: applied to elements on the current document onlyjp-mod-completer-enabled: applied to editors that can host a completerjp-mod-commandMode: applied to a notebook in command modejp-mod-editMode: applied to a notebook in edit modejp-mod-has-primary-selection: applied to editors that have a primary selectionjp-mod-in-leading-whitespace: applied to editors that have a selection within the beginning whitespace of a linejp-mod-at-line-beginning: applied to editors that can host a completer and have a selection within the beginning whitespace of a linejp-mod-tooltip: applied to the body when a tooltip exists on the pagejp-mod-trusted: applied to widgets that include trusted content; do not use this as source of truth about trust statusCSS selectors that target data attributes
[data-jp-code-runner]: applied to widgets that can run code[data-jp-interaction-mode="terminal"]: applied when a code console is in terminal mode[data-jp-interaction-mode="notebook"]: applied when a code console is in notebook mode[data-jp-isdir]: applied to describe whether file browser items are directories[data-jp-undoer]: applied to widgets that can undo[data-type]: applied to describe the type of element, such as "document-title", "submenu", "inline"