Skip to content


Repository files navigation

Presentation Plugin

The Presentation Plugin is an extension for Grav CMS, and provides a simple way of creating fullscreen slideshows that can be navigated two-dimensionally, using the Reveal.js-library.

At its core the plugin facilitates efficient handling of content for use with the library. You can utilize Reveal.js however you want through custom initialization, and still leverage the plugin's content-handling. A demo is available and a Skeleton, as well as the demo content.


  • Presentations through two-dimensional slideshows
  • Responsive, multi-device capable styling
  • Granular control over presentation and slides
    • Cascading-styles and options with Shortcodes and the Admin-plugin
  • Portable content: Everything is contained in Markdown, including settings
  • Flexible, ambigious, recursive Page-structure
  • Extendable through your own theme or plugin
  • Print-friendly presentations, with or without notes or in text-only mode
  • Presenter-mode: A modern, powerful, easy-to-use alternative to PowerPoint
    • Include notes with your presentation
    • Synchronize Presenter-mode and the Presentation locally or remotely


Installing the presentation-plugin can be done in one of two ways. The GPM (Grav Package Manager) installation method enables you to quickly and easily install the plugin with a simple terminal command, while the manual method enables you to do so via a zip file.

GPM Installation (Preferred)

The simplest way to install this plugin is via the Grav Package Manager (GPM) through your system's terminal (also called the command line). From the root of your Grav install type:

bin/gpm install presentation

This will install the Presentation-plugin into your /user/plugins directory within Grav. Its files can be found under /your/site/grav/user/plugins/presentation.

Manual Installation

To install this plugin, just download the zip version of this repository and unzip it under /your/site/grav/user/plugins. Then rename the folder to presentation. You can find these files on GitHub or via

You should now have all the plugin files under


NOTE: This plugin is a modular component for Grav which requires Grav and the Error and Problems to operate.


This plugin will only work with Grav v1.6 or higher, as it requires PHP v7.1.3 or higher.


Before configuring this plugin, you should copy the user/plugins/presentation/presentation.yaml to user/config/plugins/presentation.yaml and only edit that copy.

Here is the default configuration and an explanation of available options:

# Enable Plugin if true, disable if false
enabled: true
# Theme to use from Reveal.js (
theme: moon
# Order of how pages are rendered
  by: folder
  dir: asc
# Load all registered CSS and JS assets
all_assets: false
# Include Theme's custom.css
theme_css: true
# Enable Reveal.js CSS
builtin_css: true
# Enable Reveal.js JS
builtin_js: true
# Enable Plugin's CSS
plugin_css: true
# Enable Plugin's JS
plugin_js: true
# Enable Plugin's dynamic text sizing
textsizing: true
# Synchronize Slide-navigation
sync: "none"
# URL Route to use for Poll-sync
api_route: "presentationapi"
# Poll-sync timeout in milliseconds
poll_timeout: 2000
# Poll-sync retry limit
poll_retry_limit: 10
# Enable Poll-sync token-authorization
token_auth: false
# Poll-sync token to use for authorization
token: Hd4HFdPvbpKzTqz
# Enable Save Content button and CTRL+SHIFT+S combo
admin_async_save: false
# Enable Save Content when typing
admin_async_save_typing: false
# Twig-template to inject below content
footer: ""
# Enable onLoad transition
transition: true
# Process HTML or raw Markdown
process: html
# Enable Plugin's shortcodes
shortcodes: true
# Default class for Presentation-shortcode
shortcode_classes: "presentation-iframe"
# Unwrap images from paragraph
unwrap_images: true
# Class to use for Content building
content: "Content"
# Class to use for Content parsing
parser: "Parser"
# Class to use for Styles, Classes, and Data management
transport: "Transport"
# Class to use for Shortcode parsing
shortcode_parser: RegularParser
# Breakpoints for responsive textsizing
  240: "16"
  320: "20"
  576: "24"
  768: "28"
  992: "32"
  1200: "36"
  1600: "40"
# Styles to use as defaults for Presentations
# Dynamic text scaling to use as defaults for Presentations
  scale: string
  modifier: float
# Stack slides horizontally or vertically (default), on thematic breaks
horizontal: false
# Options to pass to Reveal.js
  width: "100%"
  height: "100%"
  margin: "0"
  minScale: "1"
  maxScale: "1"
  transition: "fade"
  controlsTutorial: "false"
  history: "true"
  display: "flex"
  pdfSeparateFragments: false

All configuration-options available to the Reveal.js-library can be configured through options, see its documentation for available options.

Page-specific configuration

Any configuration set in presentation.yaml can be overridden through a Page's FrontMatter, like this:

title: Alice’s Adventures in Wonderland
    by: date
    dir: desc
    transition: "fade"


The Page-structure used in the Presentation-plugin is essentially the same as normally in Grav, with a few notable exceptions: Any horizontal rule, --- in Markdown and <hr /> in HTML, is treated as a thematic break, as it is defined in HTML5. This means that every Page in Grav is treated as a normal, horizontal Slide when the Plugin iterates over them, but a thematic break creates a vertical Slide.

You can have as many Pages below the root-page as you want, each of them will be treated as a Slide. When you create thematic breaks within the Page, the Slides are then created below the Page itself -- accommodating Reveal.js' two-dimensional slideshows.

For using Reveal.js itself, see their documentation on Getting Started with Presenting and Speaker View.


With Reveal.js the presentation is not entirely linear. Rather, it has a linear, left-to-right set of sections that each make up a slide, and can have additional slides going downwards. Thus you can progress through the presentation linearly starting at each section, moving downwards until the end, and continuing onto the next section, or move between them as you choose.

Further, there are Fragments that can be used within each slide. These reveal linearly like slides, but make one element appear at a time rather than the full contents of the slide.


├── 01.down-the-rabbit-hole
│   └──
├── 02.advice-from-a-caterpillar
│   └──
├── 03.were-all-mad-here
│   └──
├── 04.a-mad-tea-party
│   └──
├── 05.the-queens-crocquet-ground
│   └──
├── 06.postscript

As seen in this example structure, only the initial page uses the presentation.html.twig-template. The template used for child-pages is slide.html.twig, though the content of these pages are processed regardless of template. Naming them enables the blueprints for slides in the Admin-plugin. The plugin defines the presentation.html.twig-template, but you can override it through your theme.


The plugin emulates the logic of Cascading Style Sheets (CSS), in that pages can be assigned a class, style-property, or be hidden using FrontMatter or shortcodes. This is as simple as using class: custom-slide-class in FrontMatter or [class=custom-slide-class] with a shortcode in the Markdown-content. Styles are applied the same way, where FrontMatter accepts CSS-properties like this:

  color: green

That is, mapping each property to a value, not as a list. The same could be set for any single slide using [style-color=green], as described below. Styles are given precedence by where they appear, so the plugins looks for them in this order:

  1. Plugin-options
  2. Page FrontMatter
  3. Child page FrontMatter
  4. Page Content (Markdown) as shortcodes

The properties are gathered cumulatively, and a property farther down the chain takes precedence over a property further up.

You can of course also style the plugin using your theme's /css/custom.css-file, by targeting the .reveal-selector which wraps around all of the plugin's content. This behavior can be enabled or disabled with the theme_css-setting. All slides have an id-attribute set on their sections, which can be utilized by CSS like this:

.reveal #down-the-rabbit-hole-0 {
  background: red;

Fitting text to a slide

The plugin makes available a method of dynamically scaling text within a slide, which is similar yet distinct from what happens in PowerPoint 2016. Rather than do this scaling entirely automatically, which tends to work poorly across devices and resolutions, you set a scale and an optional modifier, eg.:


If Textsizing is enabled in the plugin's options and on the Page, the relation between block text -- any text not in a header-element -- and header-text (h1, h2, h3, h4, h5, h6) is determined by the textsize-scale-property. That is, the size of the header-element's text relative to the base font-size.

In the example above, the scale is set to the "Major Second" rhythm, and with a base font size of 16 -- the minimum font-size recommended for web -- this yields the following sizes for headers: 28.83 (h1), 25.63 (h2), 22.78 (h3), 20.25 (h4), 18 (h5), and 16 (h6). The base font size, and hence text, is adjusted upwards as the size of the screen increases to enable dynamic, responsive text-sizing. This is done through the breakpoints-option.

The modifier, if set, changes the matched breakpoint's base font size by multiplication. So if set to 1.05 it makes it 5% larger than it normally would be at this breakpoint.

Using section- or slide-specific styles

If configured with shortcodes: true any section or slide can use shortcodes to declare specific styles. These take the format of [style-property=value] and are defined in multiples, eg:


If the shortcode is found and applied, it is stripped from the further evaluated content. This method uses regular expressions for speed, and takes precedence over plugin- or page-defined styles.

Note: The syntax is restricted to [style-property=value]. Unexpected characters not conforming to alphanumerics or dashes can make the expression fail to pick up the shortcode. The style-property or value must basically conform to the [a-zA-Z0-9-]+ regular expression, separated by an equal-character (=) and wrapped in square brackets ([]). For testing, use Regex101. However, you may find it necessary to wrap the value in double quotes for the parser to understand it.

Center content

To center content vertically in the slide, when Reveal.js has display: 'flex' set, you need to add justify-content: center to the slides. This is as simple as adding the following to a Page's FrontMatter:

  justify-content: center

Or the shortcode [style-justify-content=center] to an individual slide.

Full background image, video, or website with Reveal.js, through data-attributres

Reveal.js supports easy usage of background images, videos, or websites for slides, with their Slide backgrounds. As well as inline styles through shortcodes, any property that begins with data is passed as a data-attribute to the slide, so you can do things like add a background image:


Background video:


Background website:


Foreground (interactive) website:


When using data-background-interactive, the iFrame can be interacted with. Therefore you must manually click the control arrows of the presentation to navigate away from this slide. Slides with background iFrames always use the full width and height of the browser window.

Note: It may be necessary to wrap the value/parameter of the shortcode in double quotes, like [data-background-iframe=""], for it to work properly.

A big anchor overlaying the slide

A link-overlay-shortcode is available for creating a link that overlays the slide, apt for use with backgrounds. For example: [link-overlay=""].


Since version 3.1.4 the plugin is more flexible in how it looks for custom styles. You can name these style or styles, or nest them within presentation in a Page's FrontMatter. The plugin-configuration looks for style then styles, and when processing slides it continues looking within presentation. Here's an example from FrontMatter, where style is found first and therefore applied.

  justify-content: center
  justify-content: space-around
    justify-content: space-between
    justify-content: space-evenly


Each slide can have notes associated with it, like a PowerPoint-presentation would. These can be set on any slide using [notes] ... [/notes], where the shortcodes should envelop the Markdown-content that makes up your notes. Eg:


- Rabbits don't lay eggs
- Porpoises don't tell lies
- Camels don't smoke cigarettes





FOSSA Status