How to Add a Custom Footer to Sphinx Documentation? (Restructuredtext)

How can I add a custom footer to Sphinx documentation?

You have to extend the default layout by providing an html file like this:

{% extends '!layout.html' %}

{% block footer %}
<!-- your html code here -->
{% endblock %}

Save this in a _templates/ subdirectory as layout.html and make sure to tell conf.py where to find this directory:

# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']

More information on templating can be found here: https://www.sphinx-doc.org/en/master/templating.html

Trouble with custom footer in sphinx-rtd-theme

So I found a workaround.

1. Copy existing RTD html files

I copied the existing RTD .html files from my virtual environment folder. On my system it was located at the usual place:

.../Miniconda3/envs/my_env_name/Lib/site-packages/sphinx_rtd_theme/

I found the following files:

  • breadcrumbs.html
  • footer.html
  • Layout.html
  • search.html
  • searchbox.html
  • theme.conf
  • versions.html

I copied those to my working directory for my project:

.../Documentation-repo/Sphinx/root/source/_templates/

2. Edit conf.py file in working directory

I opened my conf.py file and changed the following:

# Add any paths that contain templates here, relative to this directory.
# Uncomment the line below to enable customized template #
#
# templates_path = ['_templates']

to this:

# Add any paths that contain templates here, relative to this directory.
# Uncomment the line below to enable customized template #
#
templates_path = ['_templates']

3. Add new content to footer.html file

I opened footer.html and edited it to add the content I wanted at the bottom. In my case it was as simple as adding my single sentence of changes below the {%- block extrafooter %} {% endblock %} line. Easy. Might not be the perfect solution but it works for what I need.

Adding header and footer to PDF generated using rst2pdf and spinx

The answer I came up with is from piecing together information from:

  • The rst2pdf documentation's discussion of styles and multiple stylesheets, which taught me that ordering of stylesheets matter and that custom stylesheets only need to define what is being overridden or added to previous stylesheets
  • The rst2pdf source code for built-instyles which shows that the stylesheets are best represented as YAML, and how they are structured, along with the source for the rst2pdf style Python module to better understand how rst2pdf resolves the locations and extensions for the stylesheet files
  • An rst2pdf issues that has an example of rendering a footer with a stylesheet

So what I did was create a stylesheet named draft.yaml and place it a _styles subdirectory of the document source code, which looked like:

pageTemplates:
decoratedPage:
defaultFooter: |
.. class:: right

###Page###

.. class:: draft

DRAFT - DO NOT RELEASE

defaultHeader: &draftCentered |

.. class:: draft

DRAFT - DO NOT RELEASE

mainPage: &draftTopAndBottom
defaultFooter: *draftCentered
defaultHeader: *draftCentered
showFooter: true
showHeader: true

coverPage: *draftTopAndBottom

emptyPage: *draftTopAndBottom

styles:
draft: {alignment: center, parent: bodytext, fontName: fontSansBold}

noting that the stylesheet processor supports anchors and aliases, that I am simply modifying existing page templates to include a default header and footer on all of the pages, and that I could define and use my own style to apply in the header and footer. I had wanted try using table syntax to place the page number and footer banner on the same line like can be done in the body of the document as shown here, but it kept trying to treat the table syntax as a reference substitution.

To get this working with Sphinx and rst2pdf, I needed to add some additional configuration information in conf.py - first by adding rst2pdf.pdfbuilder to the list of extensions, and then the following variable definitions to control the PDF rendering:

# -- Options for PDF output ----------------------------------------------
pdf_documents = [('index', u'mydoc', u'My Documentation', u'My Project'),]
pdf_stylesheets = ['sphinx', 'letter', 'draft']
pdf_style_path = ['source/_styles']

With this configuration and the stylesheet in place, running sphinx with pdf builder the will apply the built-in sphinx and letter rst2pdf stylesheets on top of the rst2pdf defaults, and then my custom draft rst2pdf stylesheet, and produce the desired banner text at the top and bottom of each page.

How do I set up custom styles for reStructuredText, Sphinx, ReadTheDocs, etc.?

Edit: as of 2021 the following answer is outdated, please use html_css_files = [] in your conf.py instead of using the application API after version 1.8 (current Sphinx version at time of writing is 4.1.1). The add_stylesheet option below has been renamed add_css_file in version 1.8, and seems more intended for Sphinx extension developers.

Assumptions

Your RTD doc set has something like the following structure:

  • (root path)
    • (some other stuff not germane to this discussion)
    • _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.

Use Case: Hatnotes

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.

Step 1: Create Custom CSS

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 ; }

Step 2: Add Styles to Templates

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…

Step 3: Add Stylesheets to the Theme

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.

Finishing the Use Case

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.

End State

Your doc repository now has this stuff in it:

  • (root path)
    • _static/
      • css/
        • (custom CSS files…)
    • _templates/
      • layout.html(adds your custom CSS to the default layout)
    • conf.py(with new function to add custom CSS to app's theme)

Modifying content width of the Sphinx theme 'Read the Docs'

Another option is to create a stylesheet in source/_static with just the css you want, e.g.

.wy-nav-content {
max-width: none;
}

or

.wy-nav-content {
max-width: 1200px !important;
}

Make sure the directory is referenced in source/conf.py - I believe by default there's a line to do this, i.e.

# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']

Then create a custom layout in source/_templates/layout.html and do something like this to include your stylesheet

{% extends "!layout.html" %}
{% block extrahead %}
<link href="{{ pathto("_static/style.css", True) }}" rel="stylesheet" type="text/css">
{% endblock %}

Assuming you called your stylesheet style.css

Sphinx, reStructuredText show/hide code snippets

I think the easiest way to do this would be to create a custom Sphinx theme in which you tell certain html elements to have this functionality. A little JQuery would go a long way here.

If, however you want to be able to specify this in your reStructuredText markup, you would need to either

  • get such a thing included in Sphinx itself or
  • implement it in a Sphinx/docutils extension...and then create a Sphinx theme which knew about this functionality.

This would be a bit more work, but would give you more flexibility.



Related Topics



Leave a reply



Submit