I want to extend the theme used by Sphinx and ReadTheDocs with my own custom styles.
What is the best way I can do this so that my changes will stick?
Edit: as of 2021 the following answer is outdated, please use
html_css_files = []
in yourconf.py
instead of using the application API after version 1.8 (current Sphinx version at time of writing is 4.1.1). Theadd_stylesheet
option below has been renamedadd_css_file
in version 1.8, and seems more intended for Sphinx extension developers.
Your RTD doc set has something like the following structure:
_static/
_templates/
conf.py
You're also building locally using sphinx-build
or sphinx-autobuild
using the default theme, but your deployed server might use the sphinx-rtd-theme
instead.
For this illustration, I'm going to show how to create custom styling for "hatnotes", a concept which is prevalent in MediaWiki docs and which corresponds roughly to the admonition
construct in RST. You can apply what's shown here to create any custom CSS and include it in your doc set.
The custom CSS file should go somewhere under the _static/
directory, as that's where the build process and scripts will find it. I would encourage a css/
subdirectory, since you might have other customizations to add, like JavaScript files.
Create your custom CSS file and put it in this directory. Write your style specifications as an overlay to whatever might already exist in the theme you'll be using in the build. Also don't assume anything about whether your style will override an existing style in the theme, as you can't guarantee when your styles will be added in relation to the default ones.
Here's my custom CSS for hatnotes. I saved this at _static/css/hatnotes.css
.
.hatnote
{
border-color: #c8c8c8 ;
border-style: solid ;
border-width: 1px ;
font-size: x-small ;
font-style: italic ;
margin-left: auto ;
margin-right: auto ;
padding: 3px 2em ;
}
.hatnote-gray { background-color: #e8e8e8 ; color: #000000 ; }
.hatnote-yellow { background-color: #ffffe8 ; color: #000000 ; }
.hatnote-red { background-color: #ffe8e8 ; color: #000000 ; }
.hatnote-icon { height: 16px ; width: 16px ; }
For the default theme, it is sufficient to create a template that overrides the default layout.html
to add your custom CSS to the layout. Use of templates is well documented at sphinxdoc.org. In your override template, simply set the css-files
variable (an array) with an appended list of your custom CSS files.
Here is my template which adds the hatnotes CSS. I saved this as _templates/layout.html
.
{% extends "!layout.html" %}
{% set css_files = css_files + [ "_static/css/hatnotes.css" ] %}
That's all you need to do for the default theme. For the Sphinx/RTD theme, there's an additional step, where you…
For the Sphinx/RTD theme, your template will be ignored. Instead of using the template mechanism, you have to add a function to your conf.py
file which adds the CSS file to the app's theme. Somewhere near where your conf file sets the html_theme
attribute, add something like the following:
def setup(app):
app.add_stylesheet( "css/hatnotes.css" )
Note that, this time, there's no _static/
at the front of the path; the add_stylesheet()
function assumes that part of the path.
Now that you've set up your custom styles for both the default theme and the Sphinx/RTD theme, you can actually use them in your doc.
Following the usual paradigm of defining stock hatnotes as "templates" in MediaWiki (sorry, not the same as templates in Sphinx and RTD), I set up an includes/
directory where all my hatnotes would be stored.
Here's how to construct a hatnote with the custom style information. This file is includes/hatnotes/stub-article.rst
.
.. container:: hatnote hatnote-gray
|stub| This article is a stub. Please improve the docs by expanding it.
.. |stub| image:: /images/icons/stub.png
:class: hatnote-icon
Here we set up our "stub" hatnote to have the default hatnote styling, the gray background, and use a "stub" icon as the inline image, with the hatnote-icon
style applied to that image.
Now we can use the file as an included resource in a document.
Foo Article
===========
.. include:: /includes/hatnotes/stub-article.rst
Blah blah I haven't written this article yet.
Whether you're using the local default theme or the Sphinx/RTD theme, the hatnote will be rendered with the styles you added by setting up the _templates/layout.html
template and the conf.py
script to both include the custom CSS file you put under the _static/
directory.
Your doc repository now has this stuff in it:
_static/
css/
_templates/
layout.html
— (adds your custom CSS to the default layout)
conf.py
— (with new function to add custom CSS to app's theme)
I don't know which is most "official" but if you go to the "customisation" page of the Furo theme (developed by one of the Sphinx developers) and then scroll to "Custom CSS Files" it links to a guide to "injecting code" which in turn simply links out to ReadTheDocs's page on Adding Custom CSS which does not suggest running Python code (as the answers above do) but setting a conf variable, which seems better.
html_css_files = [
'css/custom.css',
]
Adding to the accepted answer: There are various other approaches for this, e.g. adding to footer or adding to extrahead. The latter is recommended by the RTD docs.
Also I found the setup()
function was never necessary, as long as you have html_static_path = ['_static']
in your conf.py
.
Note that normally, you should replace the absolute path [ "_static/css/hatnotes.css" ]
with [ pathto("_static/css/hatnotes.css", True) ]
or the style sheet will not be loaded for RST files inside subdirectories, but it is evidently unnecessary for the accepted answer. Not sure why.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With