css.rst 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. .. _css:
  2. CSS Patterns
  3. ============
  4. This document describes the patterns we are using to organize and write
  5. CSS for JupyterLab. JupyterLab is developed using a set of npm packages
  6. that are located in ``packages``. Each of these packages has its own
  7. style, but depend on CSS variables defined in a main theme package.
  8. CSS checklist
  9. -------------
  10. - CSS classnames are defined inline in the code. We used to put them as
  11. all caps file-level ``const``\ s, but we are moving away from that.
  12. - CSS files for packages are located within the ``style``
  13. subdirectory and imported into the plugin's ``index.css``.
  14. - The JupyterLab default CSS variables in the ``theme-light-extension``
  15. and ``theme-dark-extension`` packages are used to style packages
  16. wherever possible. Individual packages should not npm-depend on
  17. these packages though, to enable the theme to be swapped out.
  18. - Additional public/private CSS variables are defined by plugins
  19. sparingly and in accordance with the conventions described below.
  20. CSS variables
  21. -------------
  22. We are using native CSS variables in JupyterLab. This is to enable
  23. dynamic theming of built-in and third party plugins. As of December
  24. 2017, CSS variables are supported in the latest stable versions of all
  25. popular browsers, except for IE. If a JupyterLab deployment needs to
  26. support these browsers, a server side CSS preprocessor such as Myth or
  27. cssnext may be used.
  28. Naming of CSS variables
  29. ^^^^^^^^^^^^^^^^^^^^^^^
  30. We use the following convention for naming CSS variables:
  31. - Start all CSS variables with ``--jp-``.
  32. - Words in the variable name should be lowercase and separated with
  33. ``-``.
  34. - The next segment should refer to the component and subcomponent, such
  35. as ``--jp-notebook-cell-``.
  36. - The next segment should refer to any state modifiers such as
  37. ``active``, ``not-active`` or ``focused``:
  38. ``--jp-notebook-cell-focused``.
  39. - The final segment will typically be related to a CSS properties, such
  40. as ``color``, ``font-size`` or ``background``:
  41. ``--jp-notebook-cell-focused-background``.
  42. Public/private
  43. ^^^^^^^^^^^^^^
  44. Some CSS variables in JupyterLab are considered part of our public API.
  45. Others are considered private and should not be used by third party
  46. plugins or themes. The difference between public and private variables
  47. is simple:
  48. - All private variables begin with ``--jp-private-``
  49. - All variables without the ``private-`` prefix are public.
  50. - Public variables should be defined under the ``:root``
  51. pseudo-selector. This ensures that public CSS variables can be
  52. inspected under the top-level ``<html>`` tag in the browser's dev
  53. tools.
  54. - Where possible, private variables should be defined and scoped under
  55. an appropriate selector other than ``:root``.
  56. CSS variable usage
  57. ^^^^^^^^^^^^^^^^^^
  58. JupyterLab includes a default set of CSS variables in the file
  59. `packages/theme-light-extension/style/variables.css <https://github.com/jupyterlab/jupyterlab/blob/3.4.x/packages/theme-light-extension/style/variables.css>`_.
  60. To ensure consistent design in JupyterLab, all built-in and third party
  61. extensions should use these variables in their styles if at all
  62. possible. Documentation about those variables can be found in the
  63. ``variables.css`` file itself.
  64. Plugins are free to define additional public and private CSS variables
  65. in their own ``index.css`` file, but should do so sparingly.
  66. Again, we consider the names of the public CSS variables in this package
  67. to be our public API for CSS.
  68. File organization
  69. -----------------
  70. We are organizing our CSS files in the following manner:
  71. - Each package in the top-level ``packages`` directory should contain
  72. any CSS files in a ``style`` subdirectory that are needed to style
  73. itself.
  74. - All local styles should be consolidated into a ``style/base.css`` file.
  75. - The top level ``index.css`` file is templated by ``buildutils`` as
  76. part of the ``integrity`` script. It imports the CSS in dependency order,
  77. ending with the local ``./base.css``. CSS from external libraries is
  78. determined by their ``style`` field in ``package.json``. If additional
  79. files are desired or the external library does not have a ``style`` field,
  80. we use the ``jupyterlab: { "extraStyles": { "fooLibrary": ["path/to/css"] } }``
  81. 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``.
  82. CSS class names
  83. ---------------
  84. CSS class naming conventions
  85. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  86. We have a fairly formal method for naming our CSS classes.
  87. First, CSS class names are associated with TypeScript classes that
  88. extend ``lumino.Widget``:
  89. The ``.node`` of each such widget should have a CSS class that matches
  90. the name of the TypeScript class:
  91. .. code:: TypeScript
  92. class MyWidget extends Widget {
  93. constructor() {
  94. super();
  95. this.addClass('jp-MyWidget');
  96. }
  97. }
  98. Second, subclasses should have a CSS class for both the parent and
  99. child:
  100. .. code:: TypeScript
  101. class MyWidgetSubclass extends MyWidget {
  102. constructor() {
  103. super(); // Adds `jp-MyWidget`
  104. this.addClass('jp-MyWidgetSubclass');
  105. }
  106. }
  107. In both of these cases, CSS class names with caps-case are reserved for
  108. situations where there is a named TypeScript ``Widget`` subclass. These
  109. classes are a way of a TypeScript class providing a public API for
  110. styling.
  111. Third, children nodes of a ``Widget`` should have a third segment in the
  112. CSS class name that gives a semantic naming of the component, such as:
  113. - ``jp-MyWidget-toolbar``
  114. - ``jp-MyWidget-button``
  115. - ``jp-MyWidget-contentButton``
  116. In general, the parent ``MyWidget`` should add these classes to the
  117. children. This applies when the children are plain DOM nodes or
  118. ``Widget`` instances/subclasses themselves. Thus, the general naming of
  119. CSS classes is of the form ``jp-WidgetName-semanticChild``. This enables
  120. the styling of these children in a manner that is independent of the
  121. children implementation or CSS classes they have themselves.
  122. Fourth, some CSS classes are used to modify the state of a widget:
  123. - ``jp-mod-active``: applied to elements in the active state
  124. - ``jp-mod-hover``: applied to elements in the hover state
  125. - ``jp-mod-selected``: applied to elements while selected
  126. Fifth, some CSS classes are used to distinguish different types of a
  127. widget:
  128. - ``jp-type-separator``: applied to menu items that are separators
  129. - ``jp-type-directory``: applied to elements in the file browser that
  130. are directories
  131. Edge cases
  132. ^^^^^^^^^^
  133. Over time, we have found that there are some edge cases that these rules
  134. don't fully address. Here, we try to clarify those edge cases.
  135. **When should a parent add a class to children?**
  136. Above, we state that a parent (``MyWidget``), should add CSS classes to
  137. children that indicate the semantic function of the child. Thus, the
  138. ``MyWidget`` subclass of ``Widget`` should add ``jp-MyWidget`` to itself
  139. and ``jp-MyWidget-toolbar`` to a toolbar child.
  140. What if the child itself is a ``Widget`` and already has a proper CSS
  141. class name itself, such as ``jp-Toolbar``? Why not use selectors such as
  142. ``.jp-MyWidget .jp-Toolbar`` or ``.jp-MyWidget > .jp-Toolbar``?
  143. The reason is that these selectors are dependent on the implementation
  144. of the toolbar having the ``jp-Toolbar`` CSS class. When ``MyWidget``
  145. adds the ``jp-MyWidget-toolbar`` class, it can style the child
  146. independent of its implementation. The other reason to add the
  147. ``jp-MyWidget-toolbar`` class is if the DOM structure is highly
  148. recursive, the usual descendant selectors may not be specific to target
  149. only the desired children.
  150. When in doubt, there is little harm done in parents adding selectors to
  151. children.
  152. .. _css-selectors:
  153. Commonly used CSS selectors
  154. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  155. We use CSS selectors to decide which context menu items to display and what command
  156. to invoke when a keyboard shortcut is used. The following common CSS selectors are
  157. intended to be used for adding context menu items and keyboard shortcuts.
  158. **CSS classes that target widgets and their children**
  159. - ``jp-Activity``: applied to elements in the main work area
  160. - ``jp-Cell``: applied to cells
  161. - ``jp-CodeCell``: applied to code cells
  162. - ``jp-CodeConsole``: applied to consoles
  163. - ``jp-CodeConsole-content``: applied to content panels in consoles
  164. - ``jp-CodeConsole-promptCell``: applied to active prompt cells in consoles
  165. - ``jp-DirListing-content``: applied to contents of file browser directory listings
  166. - ``jp-DirListing-item``: applied to items in file browser directory listings
  167. - ``jp-FileEditor``: applied to file editors
  168. - ``jp-ImageViewer``: applied to image viewers
  169. - ``jp-InputArea-editor``: applied to cell input area editors
  170. - ``jp-Notebook``: applied to notebooks
  171. - ``jp-SettingEditor``: applied to setting editors
  172. - ``jp-SideBar``: applied to sidebars
  173. - ``jp-Terminal``: applied to terminals
  174. **CSS classes that describe the state of a widget**
  175. - ``jp-mod-current``: applied to elements on the current document only
  176. - ``jp-mod-completer-enabled``: applied to editors that can host a completer
  177. - ``jp-mod-commandMode``: applied to a notebook in command mode
  178. - ``jp-mod-editMode``: applied to a notebook in edit mode
  179. - ``jp-mod-has-primary-selection``: applied to editors that have a primary selection
  180. - ``jp-mod-in-leading-whitespace``: applied to editors that have a selection within the beginning whitespace of a line
  181. - ``jp-mod-tooltip``: applied to the body when a tooltip exists on the page
  182. **CSS selectors that target data attributes**
  183. - ``[data-jp-code-runner]``: applied to widgets that can run code
  184. - ``[data-jp-interaction-mode="terminal"]``: applied when a code console is in terminal mode
  185. - ``[data-jp-interaction-mode="notebook"]``: applied when a code console is in notebook mode
  186. - ``[data-jp-isdir]``: applied to describe whether file browser items are directories
  187. - ``[data-jp-undoer]``: applied to widgets that can undo
  188. - ``[data-type]``: applied to describe the type of element, such as "document-title", "submenu", "inline"