Reveal.js: How to show same content in every page (same header/footer, by example) when exporting to pdf

Created on 23 Feb 2014  ·  17Comments  ·  Source: hakimel/reveal.js

With Reveal.js there is no way of showing same content in every page (same header/footer, by example) when exporting to pdf. For solving it I have used some JQuery magic in my fork of Reveal.js in the following way:

What I want is that the following HTML be added in every page.

<div class="topbar">
    <h1 class="titulo">Title text</h1><image class="logo" src="images/logo_tegnix.png">
</div>

This works in the navigator if we place it before the <section> labels, but for showing it in every PDF page we must repeat the HTML fragment in every section.

So I used the JQuery code to avoid repeating:

  • if we want to get the PDF output (the URL contains ?print-pdf) insert automatically in every slide, after <section>
  • if shown in a navigator, insert only once after <div class="reveal">
var html_barra = '<div class="topbar"><h1 class="titulo">' + titulo + 
'</h1><image class="logo" src="images/logo_tegnix.png"></div>';
if ( window.location.search.match( /print-pdf/gi ) ) {
    $('section').append(html_barra);
}
else {
    $('div.reveal').append(html_barra);
}

Note that titulo is the variable name for title text.

You can see online demo, pdf export and download my fork from here.

question

Most helpful comment

The methods documented in this issue don't work quite right anymore, so I have found a new method. The main change is adding the elements to the slide-background <div> (instead of section, slides, or reveal). This <div> is dynamically generated, so we must wait for the Reveal.js ready event. When printing there is a slight delay followed by unnecessary animation of the headers and footers moving into place, but all the headers/footers are rendered in the PDF as desired.

Pseudo-code:

  1. Style header/footer <div> so they are positioned as desired.
  2. Create hidden header/footer <div>
  3. On Reveal.js ready event, copy header/footer <div> into each .slide-background <div>

Code: this can be copy-pasted into the end of a reveal.js file (right before the end </body> tag):

<style type="text/css">
    /* 1. Style header/footer <div> so they are positioned as desired. */
    #header-left {
        position: absolute;
        top: 0%;
        left: 0%;
    }
    #header-right {
        position: absolute;
        top: 0%;
        right: 0%;
    }
    #footer-left {
        position: absolute;
        bottom: 0%;
        left: 0%;
    }
</style>

<!-- 2. Create hidden header/footer <div> -->
<div id="hidden" style="display:none;">
    <div id="header">
        <div id="header-left">HEADER-LEFT</div>
        <div id="header-right">HEADER-RIGHT</div>
        <div id="footer-left">FOOTER-LEFT</div>
    </div>
</div>

<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<script type="text/javascript">
    // 3. On Reveal.js ready event, copy header/footer <div> into each `.slide-background` <div>
    var header = $('#header').html();
    if ( window.location.search.match( /print-pdf/gi ) ) {
        Reveal.addEventListener( 'ready', function( event ) {
            $('.slide-background').append(header);
        });
    }
    else {
        $('div.reveal').append(header);
   }
</script>

All 17 comments

I forgot to say I really love your work! I have written a post (in Spanish) in my blog here explaining what is Reveal.js, how to use it and what my fork is for.

Thanks for sharing! I'm sure that will be useful to someone else when trying to add a fixed header/footer.

Will this at some point be integrated into reveal.js?

Complete example:

    <body>
        <style type="text/css">
            #header-left {
                position: absolute;
                top: 0%;
                left: 0%;
            }
            #header-right {
                position: absolute;
                top: 0%;
                right: 0%;
            }
            #footer-left {
                position: absolute;
                bottom: 0%;
                left: 0%;
            }
        </style>

        <div id="hidden" style="display:none;">
            <div id="header">
                <div id="header-left">…</div>
                <div id="header-right">…</div>
                <div id="footer-left">…</div>
            </div>
        </div>

        <div class="reveal">
            <div class="slides">
                …
            </div>
        </div>

        <script src="reveal.js/lib/js/head.min.js"></script>
        <script src="reveal.js/js/reveal.js"></script>

        <script>
            …
        </script>

        <script src="jquery/jquery-2.1.3.min.js"></script>

        <script type="text/javascript">
            var header = $('#header').html();
            if ( window.location.search.match( /print-pdf/gi ) ) {
                $('.slides > section').prepend(header);
            }
            else {
                $('.slides').prepend(header);
            }
        </script>
    <body>

Note that I prepend to .slides and not .reveal for the screen version, as I want the text to be in the slide area, not outside.

Also note that I prepend to .slides > section instead of just section in the print version, as otherwise the header would appear twice on the initial slide of a 2D series (nested sections: <section><section>…</section></section>) and badly broken on all other slides.

Printing is still pretty broken with this code:

<section>
  The header will appear badly placed, square in the slide.
</section>
<section>
  <section>
    The header will appear fine here.
  </section>
  <section>
    It will not appear here at all.
  </section>
</section>

Still, this is a lot better than no headers at all, especially since I only need the horizontal slides in my printout (#1168).

Hi, I added a link in the wiki to this issue at https://github.com/hakimel/reveal.js/wiki/Example-Presentations

The methods documented in this issue don't work quite right anymore, so I have found a new method. The main change is adding the elements to the slide-background <div> (instead of section, slides, or reveal). This <div> is dynamically generated, so we must wait for the Reveal.js ready event. When printing there is a slight delay followed by unnecessary animation of the headers and footers moving into place, but all the headers/footers are rendered in the PDF as desired.

Pseudo-code:

  1. Style header/footer <div> so they are positioned as desired.
  2. Create hidden header/footer <div>
  3. On Reveal.js ready event, copy header/footer <div> into each .slide-background <div>

Code: this can be copy-pasted into the end of a reveal.js file (right before the end </body> tag):

<style type="text/css">
    /* 1. Style header/footer <div> so they are positioned as desired. */
    #header-left {
        position: absolute;
        top: 0%;
        left: 0%;
    }
    #header-right {
        position: absolute;
        top: 0%;
        right: 0%;
    }
    #footer-left {
        position: absolute;
        bottom: 0%;
        left: 0%;
    }
</style>

<!-- 2. Create hidden header/footer <div> -->
<div id="hidden" style="display:none;">
    <div id="header">
        <div id="header-left">HEADER-LEFT</div>
        <div id="header-right">HEADER-RIGHT</div>
        <div id="footer-left">FOOTER-LEFT</div>
    </div>
</div>

<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<script type="text/javascript">
    // 3. On Reveal.js ready event, copy header/footer <div> into each `.slide-background` <div>
    var header = $('#header').html();
    if ( window.location.search.match( /print-pdf/gi ) ) {
        Reveal.addEventListener( 'ready', function( event ) {
            $('.slide-background').append(header);
        });
    }
    else {
        $('div.reveal').append(header);
   }
</script>

I am in the middle of doing my first reveal slide. I appreciate @Leftium's work, but the lack of an exportable footer which won't break when reveal updates itself doesn't exactly inspire me with confidence.

@Leftium, Thank you for sharing! I just used your approach and the result looks just right. 👍
@camerongreen, Did you manage to find another way?

Another example is here

For others who wind up here and are interested in @Leftium's solution: if you're using Markdown as input with pandoc for conversion, you can put this additional code in a separate file like footer.html and then include it when generating the HTML with --include-after-body="footer.html".

@sboisen, can you point to an example to such a 'footer.html'. I cannot make it work.

@antaldaniel Attached is an example i used to include a logo in the footer (renamed to .txt so Git will let me upload it).
tmp-footer.html.txt

Well, thank you very much...! I read this solution, I was just wondering how to do this when I am rendering from RStudio all the slides.

title: "Habits"
output:
html_document:
includes:
in_header: header.html
before_body: doc_prefix.html

after_body: doc_suffix.html

The first part can go to a style.css that I can add to the yaml, that is clear. I am wondering where to put the html bits, in_header or before_body?

I don't know about RStudio. In my case, i'm rendering via shell script using a pandoc command line like this:

pandoc -t revealjs --standalone --self-contained -o bibletechslides-shared.html bibletechslides.md -V revealjs-url=/Users/sboisen/local/reveal.js --slide-level=2 --css slides.css --include-after-body="footer.html"

I'm pretty sure the --include-after-body parameter is specific to pandoc.

The methods documented in this issue don't work quite right anymore, so I have found a new method. The main change is adding the elements to the slide-background

(instead of section, slides, or reveal). This
is dynamically generated, so we must wait for the Reveal.js ready event. When printing there is a slight delay followed by unnecessary animation of the headers and footers moving into place, but all the headers/footers are rendered in the PDF as desired.

Pseudo-code:

1. Style header/footer <div> so they are positioned as desired.

2. Create hidden header/footer <div>

3. On Reveal.js ready event, copy header/footer <div> into each `.slide-background` <div>

Code: this can be copy-pasted into the end of a reveal.js file (right before the end tag):

<style type="text/css">
    /* 1. Style header/footer <div> so they are positioned as desired. */
    #header-left {
        position: absolute;
        top: 0%;
        left: 0%;
    }
    #header-right {
        position: absolute;
        top: 0%;
        right: 0%;
    }
    #footer-left {
        position: absolute;
        bottom: 0%;
        left: 0%;
    }
</style>

<!-- 2. Create hidden header/footer <div> -->
<div id="hidden" style="display:none;">
    <div id="header">
        <div id="header-left">HEADER-LEFT</div>
        <div id="header-right">HEADER-RIGHT</div>
        <div id="footer-left">FOOTER-LEFT</div>
    </div>
</div>

<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<script type="text/javascript">
    // 3. On Reveal.js ready event, copy header/footer <div> into each `.slide-background` <div>
    var header = $('#header').html();
    if ( window.location.search.match( /print-pdf/gi ) ) {
        Reveal.addEventListener( 'ready', function( event ) {
            $('.slide-background').append(header);
        });
    }
    else {
        $('div.reveal').append(header);
   }
</script>

Very nice.. thx a lot..
any idea/solution for hiding it on the first slide?

try Kinzi Print Jquery Plugin, it's great and you can print header/footer on every page

http://kinziprint.com/

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Seth-Gecko picture Seth-Gecko  ·  4Comments

justmytwospence picture justmytwospence  ·  4Comments

MurhafSousli picture MurhafSousli  ·  5Comments

alesarrett picture alesarrett  ·  5Comments

Enosinger picture Enosinger  ·  4Comments