lecture.studio

Two-column layouts in Marp: flex, grid, tables, bg split

Marp has no column syntax, so a two-column slide is one of four things: a Markdown table (no setup, rigid), an image split with ![bg right:40%] (image beside text, no HTML), a flex container in HTML (<div class="columns">, the usual choice), or a CSS grid class for three or more columns. Put the class in the theme once and every deck gets it; current Marp renders a div with a class out of the box.

This guide shows each with a copy-pasteable example, then the rule for choosing, and what current and older Marp versions do with the HTML.

1. A table

| Stack | Queue |
|---|---|
| Last in, first out | First in, first out |
| `push`, `pop` | `enqueue`, `dequeue` |
| Call stack, undo | Print jobs, BFS |

No setup, works everywhere, exports everywhere. Fits when both sides are short parallel items. Does not fit when a side needs a list, a code block or an image; table cells take inline content only.

2. Image beside text with a background split

![bg right:45%](assets/queue.png)

# Queue

- `enqueue` at the tail
- `dequeue` at the head
- O(1) both ways with a linked list

The image takes the right 45% of the slide and the content flows on the left. No HTML, and the image is scaled by Marp; Marp images has the rest of the bg syntax. Fits every "diagram plus bullets" slide. Does not fit two text columns.

3. Flex columns in HTML

The general solution. Once in the theme or the front matter:

---
marp: true
style: |
  .columns { display: flex; gap: 24px; }
  .column { flex: 1; min-width: 0; }
---

Then on any slide:

<div class="columns">
<div class="column">

### Stack

- Last in, first out
- `push`, `pop`

</div>
<div class="column">

### Queue

- First in, first out
- `enqueue`, `dequeue`

</div>
</div>

The blank lines inside each div matter: they are what lets Markdown render the headings and lists inside HTML. Unequal columns: a second class in the theme (.column-wide { flex: 2; }) rather than an inline style="flex: 2", which the default HTML allowlist strips (see below). Code blocks, images and lists all work inside.

4. Grid for three or more

.columns-3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1rem; }
<div class="columns-3">
<div>

**FCFS**
simple, convoy effect

</div>
<div>

**SJF**
optimal mean wait, needs prediction

</div>
<div>

**RR**
fair, quantum-sensitive

</div>
</div>

minmax(0, 1fr) keeps a long word from widening its column. Grid is also the right tool for a two-by-two.

Does the HTML render?

Since Marp Core 4.0 (September 2024; marp-cli 4 and the current VS Code extension ship it), yes by default: Marp renders a safe allowlist of elements and attributes, and div, span, section and figure with a class, lang, dir or title attribute are on it. Tested with marp-cli 4.5.1: the flex pattern above renders with no flag at all. What the allowlist strips is inline style="…" attributes, id, and anything script-like; if you want those, opt in:

Marp Core 3 and earlier allowed only a handful of elements unless HTML was enabled, so a tool built on an old version, or an old blog post, will tell you the columns need --html. If the columns come out as plain stacked text with no error, that is the version you have, and the flag is the fix.

Choosing

Slide Use
short parallel items table
diagram beside bullets bg split
two blocks of Markdown flex columns
three or more, or a 2×2 grid

Two columns on a 16:9 slide leave about 600 px each. Lists longer than five items or code wider than 50 characters need the whole slide.

In Lecture Studio

Lecture Studio's shipped themes define two-columns and columns/column (flex) and columns-3 (grid), HTML is fully enabled in the preview (inline styles included), and the editor's Columns button inserts a two-columns block with a heading and a list on each side, so the third and fourth patterns are a click and every deck renders the same. To render the same deck outside the app, pass the theme with --theme-set to marp-cli, and --html if the deck uses inline styles. The app runs on macOS 15 or later; the assistant needs an Oberik project key.

FAQ

How do I make two columns in Marp?

Define .columns { display: flex; gap: 24px; } .column { flex: 1; } in the theme or the style: block and wrap the two halves in <div class="column"> inside <div class="columns">, with a blank line after each opening tag.

Why do my Marp columns not render?

Either the blank lines inside each div are missing, or the renderer is built on an old Marp Core that needs HTML enabled (--html in marp-cli, markdown.marp.html in VS Code). Current Marp renders a div with a class by default.

Can I put an image in one column and text in the other?

Yes, either with the flex pattern (an image in one div) or without HTML using ![bg right:45%](img.png).

How do I make three columns in Marp?

A CSS grid class: grid-template-columns: repeat(3, minmax(0, 1fr)), with one div per column.