Theming IPython Jupyter Notebooks
Summary
If you are trying to modify your ipython notebook css by changing:
~/.ipython/profile_default/static/custom/custom.css
Instead, try changing:
~/.jupyter/custom/custom.css
This is only tested on:
$ jupyter --version
4.0.6
$ ipython --version
4.0.1
$ pip3 show notebook
...
Version: 4.1.0
...
Which are the latest versions of all those packages as of now.
Details
Almost all guides to modifying of ipython notebooks css tell you to put your modifications in:
~/.ipython/profile_default/static/custom/custom.css
There is already a custom.css
file living there waiting for your changes.
I spent way too much time wondering why my css changes did nothing. First I thought that maybe profile_default
was a special profile that could not be modified. I tried creating my own profile as explained here but it still didn’t work.
I finally found one tip at the bottom of a GitHub issue on the jupyter GitHub repo that said that custom css had moved into the ~/.jupyter
directory. Specifically:
~/.jupyter/custom/custom.css
That worked.
I don’t know if this is a very recent change, but it’s strange that 99.99% of information online pointed to the old ~/.ipython/
location.
Modifications
I am using the base16-flat-dark.css
from this repo of ipython themes. I had to modify it a bit to work with jupyter.
/*
Name: Base16 Twilight Dark
Author: David Hart (http://hart-dev.com)
CodeMirror template adapted for IPython Notebook by Nikhil Sonnad (https://github.com/nsonnad/base16-ipython-notebook)
CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-chrome-devtools)
Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)
*/
/* Uncomment to use a custom font
div#notebook, div.CodeMirror, div.output_area pre, div.output_wrapper, div.prompt {
font-family: 'Custom Font Name', monospace !important;
}
*/
/*Sherif's customizations*/
/*Otherwise, a lot of backgrounds are white.*/
div#notebook {background-color: #1e1e1e; border-top: none;}
div#notebook-container {background-color: #1e1e1e;}
/*Don't need to see jupyter logo, filename, last saved, etc.*/
div#header-container { display: none; }
/*This prevents scrollable output from having an ugly grey
shadow around it*/
div.output.output_scroll {
box-shadow: none;
}
/*Scroll bars*/
::-webkit-scrollbar {
width: 12px;
}
/* Handle */
::-webkit-scrollbar-thumb {
-webkit-border-radius: 5px;
border-radius: 5px;
background: #484848;
}
::-webkit-scrollbar-thumb:window-inactive {
background: #484848;
}
/*########################*/
/* GLOBALS */
body {background-color: #1e1e1e;}
a {color: #7587a6;}
/* INTRO PAGE */
.toolbar_info, .list_container {color: #c3c3c3;}
/* NOTEBOOK */
/* comment out this line to bring the toolbar back */
/*div#maintoolbar, div#header {display: none !important;}*/
div.input_prompt {color: #9b703f;}
div.output_prompt {color: #9b859d;}
div.input_area {
border-radius: 0px;
border: 1px solid #464b50;
}
div.output_area pre {font-weight: normal; color: #a7a7a7;}
div.output_subarea {font-weight: normal; color: #a7a7a7;}
.rendered_html table, .rendered_html th, .rendered_html tr, .rendered_html td {
border: 1px #a7a7a7 solid;
color: #a7a7a7;
}
div.output_html { font-family: sans-serif; }
table.dataframe tr {border: 1px #a7a7a7;}
div.cell.selected {border-radius: 0px;}
div.cell.edit_mode {border-radius: 0px; border: thin solid #9b859d;}
div.text_cell_render, div.output_html {color: #a7a7a7;}
span.ansiblack {color: #323537;}
span.ansiblue {color: #afc4db;}
span.ansigray {color: #838184;}
span.ansigreen {color: #8f9d6a;}
span.ansipurple {color: #9b859d;}
span.ansired {color: #cf6a4c;}
span.ansiyellow {color: #f9ee98;}
div.output_stderr {background-color: #cf6a4c;}
div.output_stderr pre {color: #c3c3c3;}
.cm-s-ipython.CodeMirror {background: #1e1e1e; color: #c3c3c3;}
.cm-s-ipython div.CodeMirror-selected {background: #323537 !important;}
.cm-s-ipython .CodeMirror-gutters {background: #1e1e1e; border-right: 0px;}
.cm-s-ipython .CodeMirror-linenumber {color: #5f5a60;}
.cm-s-ipython .CodeMirror-cursor {border-left: 1px solid #838184 !important;}
.cm-s-ipython span.cm-comment {color: #9b703f;}
.cm-s-ipython span.cm-atom {color: #9b859d;}
.cm-s-ipython span.cm-number {color: #9b859d;}
.cm-s-ipython span.cm-property, .cm-s-ipython span.cm-attribute {color: #8f9d6a;}
.cm-s-ipython span.cm-keyword {color: #cf6a4c;}
.cm-s-ipython span.cm-string {color: #f9ee98;}
.cm-s-ipython span.cm-operator {color: #9b703f;}
.cm-s-ipython span.cm-builtin {color: #9b859d;}
.cm-s-ipython span.cm-variable {color: #8f9d6a;}
.cm-s-ipython span.cm-variable-2 {color: #7587a6;}
.cm-s-ipython span.cm-def {color: #cda869;}
.cm-s-ipython span.cm-error {background: #cf6a4c; color: #838184;}
.cm-s-ipython span.cm-bracket {color: #a7a7a7;}
.cm-s-ipython span.cm-tag {color: #cf6a4c;}
.cm-s-ipython span.cm-link {color: #9b859d;}
.cm-s-ipython .CodeMirror-matchingbracket { text-decoration: underline; color: #c3c3c3 !important;}
Update (11/08/2016)
I made several improvements to this css file since I published this post. The changes include styling for code blocks and image/plot background colors. You can find the latest version in my dotfiles repo.
Update (12/08/2017)
I decided to reset my “theme” to the default (at least for now), so the link to my dotfiles repo in the update above contains only an override to the font used. I’ll leave the longer css snippet in this post for those interested.