Plot

Margins

Pin the plot's inner offsets so charts align across grids and documents — and set the gutter between facet panels.

AI assisted, human approved — novem uses AI to review and keep our documentation up to date.

Note: the margins file is part of the early-access flat config tree. You can explore it interactively in the plot playground.

Margins live in one file directly under your plot's config:

plotconfig/margins

By default every side is auto: novem measures your axis labels, ticks and titles and computes the margin that fits them. An unsigned value replaces that calculation exactly; a value prefixed with + or - adjusts it. Exact margins are useful when charts must align across a grid or document, and they double as the wrap budget for wrapped category labels.

The keys are the m* family — the same prefix the axis grammar uses for its offsets: m* moves things, p* pads scales, e: picks edges.

ml:15px mr:45, mt:22
ml:60                             -- later directives win
ml:5% mb:auto                     -- % of the svg dimension
ma:+5                             -- add 5px to every auto margin
mb:-5                             -- subtract 5px from auto bottom
  • ml: mr: mt: mb: are the left, right, top and bottom margins of the plot area.
  • mx: my: ma: are side bundles, the same x/y reading the table's border and padding files use: mx: sets left+right, my: top+bottom, ma: all four. They are pure expansions — a later single-side directive overrides its half (mx:20 ml:60 leaves right at 20).
  • An unsigned pixel (px suffix optional) or % value is exact. Prefix it with + or - to adjust the measured value instead: ma:+5 adds 5px to all sides, while mb:-5 subtracts 5px from the calculated bottom. Signed percentages adjust by that percentage of the corresponding svg dimension.
  • Whitespace and commas both separate directives; several fit on one line; the last directive for a side wins; the value may be attached (ml:15) or the next token (ml: 15).
  • auto restores the measured autocompute — a later auto clears an earlier explicit value.
  • -- starts a comment, the same marker as every novem grammar.

When a plot is split into panels with facets, px: and py: set the gutters between them. Gutters are inner spacing, so they take the padding letter, and they read the same way as every other x/y in the platform: px: is the gap you cross moving horizontally (between each column of panels), py: the gap between each row:

px:12 py:8

pa: bundles both gutters, like ma: does for the sides. The gutter is by definition the leftover space after each facet carves out its label, axis and chart area. The side directives describe the outer frame of the whole surface; between panels there is no margin, only the gutter — a panel's exterior sides inherit the frame, its interior sides get the gutter, so a stacked price/volume layout comes out right with no configuration at all. Negative gutters pull panels together (overlap allowed); auto restores the theme default. Margin and gutter changes animate like any other layout change.

A line leading with the shared slicer pair selects panels by their physical grid position — rows × columns, one slicer meaning columns, negatives counting from the end — and overrides those panels' margin boxes:

0 : mt:40                         -- the first grid ROW
: -1 mr:0                         -- the last grid COLUMN
-1 mb:20                          -- one slicer = columns

Later lines win per side. Sides you don't override follow the exterior/interior rule; auto on a scoped line removes that override again.

Invalid directives are dropped, never fatal: the rest of the file still applies, and every dropped directive lands in the plot's diagnostics with its line number. The playground shows them inline.