Welcome!

Styling and Themes

This page is part of the advanced authoring path — a special case the Lupo team sets up on request. Most people don't need it.

TL;DR; A hand-authored project can be restyled three ways: a directive in a slide file's header or in a per-slide comment, an inline <style> block for a one-off tweak, or a full custom theme file for a consistent look across every slide. None of these is a toc.yml setting — they live in the Markdown and CSS files themselves.

Before you start

See Authoring in Markdown for the slide files a theme applies to — in particular the marp: true header every file needs.

A naming note before you start

toc.yml has its own style key, but that controls the narrator's speaking style — an emotion like cheerful, not how a slide looks. Visual styling, covered on this page, is a completely separate mechanism set inside the Markdown and CSS files, not in toc.yml. It's an easy mix-up because both are called "style."

Directives

A slide file is a Marp deck, so it takes Marp's directives. Set in the file's header (next to marp: true), a directive applies to every slide in the file; set again inside a single slide as an HTML comment with a leading underscore, it overrides just that slide. Lupo accepts these: paginate, header, footer, class, backgroundColor, backgroundImage, backgroundPosition, backgroundRepeat, backgroundSize, color, size and math. Anything else in the header is reported as a warning, as is an unknown directive in a comment.

---
marp: true
backgroundColor: #FFFFFF
footer: My Course
---

# A normal slide

---

<!-- _backgroundColor: #2288C9 -->
<!-- _color: #FFFFFF -->

# This slide alone is blue

Inline styling

A <style> block directly inside a slide's Markdown, scoped with normal CSS selectors, restyles just that slide:

<style>
section {
    background-color: #2288C9;
}
</style>

Custom themes

For a look you want to reuse everywhere, a custom theme is a CSS file that starts with a name comment and typically builds on the built-in default:

/* @theme customtheme */
@import 'default';

Lupo finds theme files through the project's .vscode/settings.json, under markdown.marp.themes — the same list VS Code's Marp extension reads, so a theme that previews in your editor is the one Lupo builds with. Paths are relative to the project root:

{
  "markdown.marp.themes": [
    "themes/customtheme.css"
  ]
}

Then apply it to a Markdown file through that file's own header:

---
marp: true
theme: customtheme
---

A theme named in a file but missing from that list is reported as a warning — "The theme 'customtheme' mentioned in '…' is not found in settings.json" — and the file renders with the default look instead.

A theme file uses ordinary CSS custom properties for fonts and colors, and can import a web font the same way any CSS file would:

@import url('https://fonts.googleapis.com/css2?family=Nunito&display=swap');

:root {
    --primary-font: 'Poppins', sans-serif;
    --primary-color: #2288C9;
}

If your project embeds video, keep the rule that makes it fill the slide — deleting it breaks video display:

video {
    position: fixed;
    right: 0;
    bottom: 0;
    min-width: 100%;
    min-height: 100%;
}

Editor snippets

This one's pure authoring convenience — a way to type faster in your editor, not something that changes how a project renders. VS Code snippets scoped to Markdown files let you type a short prefix and expand it into a template. Add a your-name.code-snippets file under .vscode/ in the project:

{
  "video": {
    "scope": "markdown",
    "prefix": "video",
    "body": [
      "<video src='$1' loop muted>"
    ],
    "description": "Insert video element"
  }
}

Typing video and pressing Tab in a Markdown file expands to the snippet body, with $1 as the first cursor stop. This is standard editor tooling — nothing about it is specific to how Lupo renders a project.

Where to go next