- Published on
Presentations as code thanks to Marp
A better way to make slides?
I have spent years dodging PowerPoint, with limited success. Whether it was me who was expected to deliver the presentation, or people imploring me to automate the creation of their slide decks, I dreaded few things more. What really pissed me off was the feeling that it really didn't need to be this hard. Why do I need to click click click, why can't I just write some code? I thought I'd try out some modern tools that aim to address exactly this problem.
I attended a meetup event named Making slides with reStructuredText (shoutout to CamPUG, they're a friendly bunch). I tend to prefer Markdown over RST but the talk got me thinking....
Goals
What I was hoping to develop was a workflow for creating simple slide decks from my editor. I don't have to present all that often, and when I do, I'm not really interested in animations and fancy transition effects. I simply want to be able to open my editor and knock out a few static slides in minutes, leveraging most of the features of Markdown. That is, text (obviously), lists, tables, embedded images and crucially, syntax highlighting of code blocks.
While HTML output might be nice, my key requirement is to able to be able to automatically create a PDF version of my presentation. One of the things I took away from the talk I attended was the robustness of PDFs . There's no need to worry about browser compatibility issues (even if these have mostly gone away these days) and pretty much any PDF viewer will have a presentation display mode. That P must mean something after all ;).
Being able to add the build step to a CI tool would be the icing on the cake. If you did loads of presentations and were likely to re-use them, how cool would it be to store the text in a git repository and be able to update them and re-produce them seamlessly?! Again, this probably isn't going to be super important for me but I decided it would be fun to play with.
Tools Considered
I did a little bit of digging and there are dozens of different tools that I could use. A few that caught my eye after a cursory search were:
- Pandoc - a versatile document converter written in Haskell which supports multiple different markup and output formats
- reveal.js - a fully-fledged js framework for creating really slick HTML slides that supports Markdown and lots more
- landslide - a tool written in Python for turning Markdown (and rST etc) into HTML
- Marp - a dedicated Markdown converter geared towards slide creation with an intuitive vscode extension
Of the above, Pandoc looks extremely useful but I was leaning towards a tool more focused on creating presentations specifically. Meanwhile, reveal.js was geared to creating fancy presentations in HTML but just seemed like overkill for my use case. I did play around with Landslide, which has the appeal of being written in Python, and it worked just fine but when I tried Marp, via the vscode plugin, I was hooked.
There are no doubt ways of achieving something similar with other tools, but the ability to type Markdown in an editor pane and have it rendered as slides in the preview pane was exactly the experience I was looking for. Ideally, with this workflow, I could knock out a simple slide deck in minutes and produce a PDF that I can present just about anywhere.
Getting Started with Marp
By installing the vscode extension, I was up and running in seconds. Of course, I know that everyone uses different editors but the extension I'm using just builds on the Marp framework and there's no reason one can't use different tools within the ecosystem to produce slides in the same way. That said, having the preview pane in my editor is the perfect workflow for me. I can write my slides and see the result in real-time.
Creating a simple slide deck is easy. All you need to do is create a Markdown file and add a front matter section with the following:
---
marp: true
---
The only other thing to understand, beyond a knowledge of Markdown, is that a new slide is indicated using a "ruler" ---
. So we could create a simple title slide and a few more pages with something like this:
# Presentations as Code with Marp!
by Alexander Sutcliffe
- [Github](https://github.com/scrambldchannel)
- [Blog](https://dashingelephant.xyz/)
---
## Agenda
- What is Marp?
- Why use it to create presentations?
- What cool features does it have?
- Conclusion
---
## What is Marp?
The [Marp Presentation Ecosystem](https://marp.app/) (Marp for short) is a collection of tools that allow you to create elegant slide decks using the familiar Markdown syntax
---
## Why use it to create presentations?
- Creating slides with wysiwg tools (e.g. PowerPoint) is a nightmare
- Concentrate on content, not bells and whistles
- Slidedecks can be committed to version control!
---
Syntax Highlighting
As I mentioned above, this is a key benefit for me. When giving technical presentations, it's quite common to want to be able to show some code, and while I will often drop to my editor to demo things live, it's nice to be able to produce a slide deck with some readable code examples included. Using Markdown to create your slides means you get this for free.
This is all getting a bit meta but, given that I'm writing this blog post in Markdown, it's difficult to illustrate! Marp will render a code block prefixed with three backticks and a language just as you would expect. That is, the following Python code will appear according to the CSS you're using in a given context.
num_mouse_clicks_for_a_ppt = 1000000
for mouse_click in num_mouse_clicks_for_a_ppt:
print(f"My RSI has been inflamed by {mouse_click} mouse clicks")
Themes
Marp comes with a few themes built in but creating your own seems well documented. For my use so far, I've been happy with the default theme but if I wanted to switch to the gaia
theme I would simply specify this in the front matter section of my file:
---
marp: true
theme: gaia
---
It's also possible to override the CSS of a theme using the <style>
tag and enclosing your custom style. By default, it will apply changes globally (i.e. to all slides) but if you use <style scoped>
, it will only affect the slide it's added to. For example, the following can be added to a slide's markdown to change the rendering of the emp
(i.e. text enclosed in **
in Markdown) tag:
<style scoped>
strong {
font-size: 64px;
color: lightblue;
}
</style>
Using directives
Directives are extensions to the Markdown syntax that Marp provides that allow you to specify desired outwith standard Markdown. In fact theme
is simply a directive. They can be used in a number of different ways. For example, rather than setting the theme
key in the front matter as above, we can use the following directive to change the theme globally:
<!-- theme: gaia -->
Another directive allows you to add pagination to slides. Again this can either be specified in the front matter:
---
marp: true
pagination: true
---
Or, alternatively, you can add the directive inline:
<!-- paginate: true -->
Using the directive inline allows you to specify that it should only take effect from the page it is added to onwards, or until it is overwritten by another inline directive.
You can further restrict the scope of a directive by prefixing it with an underscore:
<!-- _paginate: true -->
The snippet above could be used to add a page number to the current slide only (although I'm not sure why you would necessarily want to do that). Other directives are available and provide other functionality that is relevant in the context of presentations such as adding headers as footers to slides.
Images
Of course, at some point, you're likely to want to add an image or two to your presentation. Marp extends the Markdown syntax to make this a bit easier. I still found this a bit of pain (but then I find embedding images neatly into anything a bit fiddly). Basic usage would be something like this:
![](image.png)
Image can be scaled using width and height (or shorthand equivalents):
![width: 200px height: 150px](image.png)
![w: 30cm h: 20cm](image.jpg)
You can also apply css filters with Marp. To be honest, not being a full-time web developer, I didn't even know these things existed until today but I can see how some might be useful. For example, converting images to greyscale might be useful if colours aren't displaying properly for whatever reason:
![grayscale](image.gif)
You can also use the bg
keyword to set an image as the background for a slide. You can also use as many keywords as you like in combination. For example, this would set the slide background image and also set the opacity to 20% and blur the image somewhat. Something like this could be really useful for creating a cover slide or adding logos or watermarks to slides.
![bg opacity:0.2 bg blur:5px](image.png)
In the Marp docs, there is mention of advanced backgrounds (experimental at the time of writing) which offers support for using multiple images and splitting backgrounds. The standard functionality is all I see myself wanting though!
Rendering a presentation
If you are using the vscode extension, and just want to produce a pdf on an ad hoc basis, you can simply click a button and export a pdf.
Still, there's a lot more power and flexibility you can unlock if you use the Marp CLI package. You can install from npm or simply (and my preferred method) execute directly from npm using npx:
npx @marp-team/marp-cli@latest presentations_as_code.md --pdf
You'll note that I've used a flag to specify that I want to render as a pdf. HTML is the default and the Marp CLI can also output presentations in Powerpoint format and more. The CLI offers further options for customising your output. It would trivial to wrap your desired options in a simple Makefile or even to use Marp as part of a CI pipeline. I note that someone has created a Github action that can output a presentation to a Github pages which seems interesting...
What's missing?
As much as I find it hard to empathise with them, I'm sure there are PowerPoint experts out there who would be horrified at the list of things they can't do. As much as super slick animated presentations can look really cool, they're not something I really aspire to be able to create. Partly because I'm lazy and devoid of artistic talent, but also because I feel these things are often a distraction or a massive waste of time.
There is one thing I hoped would work out of the box that didn't and that is being able to embed Mermaid charts. This would make Marp perfect for my needs but the good news is that there are ways of making it work, with a little bit of effort. This issue thread outlines some workarounds and also hints that this functionality could be added via a plugin. That's right, Marp has a plugin architecture, one that I haven't really explored but that makes me excited at the possibilities!