Skip to content

Callouts and masks

A callout draws on one mark. shotlist computes the position, extends the canvas when a label or a disc needs room outside the captured region, and moves a label that would overlap one already drawn.

screenshots/recipes/order-row.yaml
marks:
  amount: { within: clip, text: $42.00 }
  status: { within: clip, text: Open }

callouts:
  - { mark: amount, text: What they owe, place: left }
  - mark: status
    text:
      - Where it stands
      - and who is waiting
    place: bottom
    dy: 12

Callout fields

Field Default Effect
markrequiredWhich mark to draw on
text—Label text: one string, or a list with one line each
n—Number shown in a disc
placeautoauto, left, right, top, bottom, or corner
badgetlAnchor for place: corner: tl tc tr ml mr bl br bc
boxtrueWhether to draw the outline
insidesee belowWhether the label or disc sits over the capture
dx0Nudge across, in image pixels
dy0Nudge down, in image pixels
padstyle.box.padDistance between the outline and the element
gapstyle.label.gapDistance between the label and the outline

Left unset, a disc (place: corner) sits inside, on the box, and a label on a named side sits outside, in a margin the canvas grows to make. An explicit place or inside is obeyed exactly. For what auto weighs, see How labels are placed.

numbered

A list is shorthand for one numbered disc per mark, in the order given:

screenshots/recipes/statblock.yaml
marks:
  header: { css: '.statblock-header' }
  abilities: { css: '.abilities' }
  defenses: { css: '.defenses' }

numbered: [header, abilities, defenses]

A mapping carries that list under marks, and applies every other key to all of them:

screenshots/recipes/statblock.yaml
marks:
  header: { css: '.statblock-header' }
  abilities: { css: '.abilities' }
  defenses: { css: '.defenses' }

numbered:
  marks: [header, abilities, defenses]
  box: false
  badge: ml
  inside: false
Key Default Effect
marksrequiredMarks to number, in order
boxtrueWhether to outline each mark
badgetlWhich corner or edge the disc anchors to
insidetrueWhether discs sit over the capture
dx, dy0Nudge, in image pixels
padstyle.box.padDistance between the outline and the element

place is not among them. A numbered disc is always corner, and badge chooses which one.

mask

A list of queries. Each matched region is painted with style.mask.fill before the callouts are drawn, so a callout may still point at a masked region.

screenshots/recipes/dashboard.yaml
mask:
  - { within: clip, css: '.updated-at' }
  - { rect: [172, 84, 52, 20] }

A mask covers every element its query matches. Add pick or nth to select one. A mask that matches nothing stops the run. With source: file, masks are literal rectangles.

Masking changes the image. To leave a region in the image but out of the --check comparison, use check.ignore instead.