quarto-shapes
CSS shape classes for Quarto documents and presentations
Style divs as shapes that can contain text and other elements. Supports fill, stroke, rotation, and sizing — all composable as classes.
Installation
quarto add emilhvitfeldt/quarto-shapesQuick Start
Add to your YAML front matter:
---
title: My Document
format: html
filters:
- shapes
---Then wrap any content in a shape div:
::: {.shape-circle fill="blue"}
Hello
:::Shape classes
Every shape is a class of the form .shape-<name>. The full catalog, grouped by category:
| Category | Shape classes |
|---|---|
| Basic geometric | .shape-circle, .shape-square, .shape-rectangle, .shape-rounded-square, .shape-oval, .shape-semicircle, .shape-pie, .shape-wedge, .shape-arc, .shape-block-arc, .shape-donut, .shape-frame |
| Polygons | .shape-triangle, .shape-diamond, .shape-pentagon, .shape-hexagon, .shape-heptagon, .shape-octagon, .shape-decagon, .shape-dodecagon, .shape-parallelogram, .shape-trapezoid |
| Stars | .shape-star-4, .shape-star, .shape-star-6, .shape-star-8, .shape-star-10, .shape-star-12, .shape-star-16, .shape-star-24, .shape-star-32, .shape-sun, .shape-starburst |
| Nature & symbols | .shape-heart, .shape-moon, .shape-cloud, .shape-lightning, .shape-teardrop, .shape-wave, .shape-double-wave, .shape-no-symbol, .shape-smiley |
| Arrows | .shape-arrow, .shape-arrow-double, .shape-notched-arrow, .shape-pentagon-arrow, .shape-arrow-striped, .shape-arrow-bent, .shape-chevron |
| Callouts & bubbles | .shape-speech-bubble, .shape-callout-round, .shape-callout-rounded, .shape-callout-oval, .shape-callout-thought, .shape-callout-cloud, .shape-callout-explosion |
| Flowchart | .shape-terminator, .shape-cylinder, .shape-document, .shape-manual-input, .shape-delay, .shape-display, .shape-stored-data, .shape-summing-junction, .shape-off-page |
| Block & functional | .shape-cross, .shape-shield, .shape-folded-corner, .shape-diagonal-stripe, .shape-scroll, .shape-wavy-flag, .shape-ribbon |
| 3D / perspective | .shape-cube, .shape-cylinder-3d, .shape-cone, .shape-pyramid |
| Math symbols | .shape-minus, .shape-multiply, .shape-divide, .shape-equals, .shape-not-equal |
| Brackets & braces | .shape-bracket-left, .shape-bracket-right, .shape-brace-left, .shape-brace-right, .shape-paren-left, .shape-paren-right |
The HTML example renders every one of these with its class name labeled underneath.
Colors, sizes, and modifiers
Colors are set with the fill= and stroke= attributes; size, stroke width, and rotation are classes. Everything is composable — mix attributes and classes on a single div, in any order:
::: {.shape-hexagon fill="none" stroke="red" .shape-stroke-lg .shape-rotate-90 .shape-md}
:::Fill — fill="…"
Sets the interior color. Accepts any CSS color — a named color (tomato), hex (#42526C), or function (rgb(52 152 219)). Use fill="none" for an outline-only shape (pair it with a stroke).
::: {.shape-circle fill="#42526C"}
:::Stroke — stroke="…" + .shape-stroke-*
Two independent axes: the outline color comes from the stroke= attribute (any CSS color), and the outline width from a class.
| Color | Width | Default width |
|---|---|---|
stroke="<any CSS color>", or stroke="none" |
.shape-stroke-sm (1) · .shape-stroke-md (3) · .shape-stroke-lg (6) · .shape-stroke-xl (10) |
3 when a stroke color is set without a width class |
Size — .shape-{sm,md,lg,full} or size="…"
Sets the shape’s bounding box. Defaults to 8rem (same as .shape-md) when no size class is given.
| Class | HTML size | Typst (print) |
|---|---|---|
.shape-sm |
4rem |
3cm |
.shape-md |
8rem |
5cm |
.shape-lg |
14rem |
8cm |
.shape-full |
100% of container |
— |
For a custom size, use the size= attribute with any length. It overrides the size classes and works in both HTML and Typst.
::: {.shape-circle fill="#42526C" size="3cm"}
:::The value is passed through to both outputs as-is, so for documents you render to both HTML and Typst use a unit valid in each (cm, mm, in, pt). Typst does not accept px.
Rotation — .shape-rotate-*
Rotates the shape clockwise in 45° steps: .shape-rotate-45, .shape-rotate-90, .shape-rotate-135, .shape-rotate-180, .shape-rotate-225, .shape-rotate-270, .shape-rotate-315.
See the HTML example for these modifiers applied across the full shape catalog.
Callout direction — direction="…"
The callout and speech-bubble shapes (.shape-callout-round, .shape-callout-oval, .shape-callout-rounded, .shape-speech-bubble) point their tail down by default. Use the direction= attribute to point the tail any direction. The body stays upright and only the pointer moves: the filter recomputes the shape as a single outline (body + spike) for the requested angle, so there is no seam even on outlined callouts.
direction= takes a compass angle in degrees, or one of the four keyword aliases:
| Value | Pointer faces |
|---|---|
0 / up |
up |
90 / right |
right |
180 / down (default) |
down |
270 / left |
left |
Any number works, so direction="225" points the tail down-left and direction="30" points up-and-to-the-right.
::: {.shape-speech-bubble fill="lightyellow" direction="up"}
Heads up!
:::
::: {.shape-callout-round fill="#4DADAD" direction="225"}
Down-left
:::Works in HTML, RevealJS, and Typst. (.shape-callout-cloud, .shape-callout-thought, and .shape-callout-explosion keep their fixed designs.)
Typst / PDF output
Shapes also render in Quarto’s typst format (PDF). The existing SVG definitions are embedded as Typst images, so every shape is available. Note these print-specific behaviors.
- Size classes map to print lengths:
.shape-sm3cm,.shape-md5cm,.shape-lg8cm. - Content is centered within the shape’s bounding box, not its visual outline.