Constraints

Constraints declaratively control element positioning. Add them to the constraints array in a scene document or via the addConstraint operation.

Building an agent integration? See How AI Agents Should Use Zindex for the recommended workflow for scene creation, incremental edits, revision handling, validation, normalization, and rendering.

Each constraint has a type, a unique id, and type-specific parameters.

align

Align elements along a single axis by their centers.

{
  "id": "c1",
  "type": "align",
  "axis": "y",
  "elements": ["btn1", "btn2", "btn3"]
}
ParameterRequiredDescription
axisYes"x" or "y" - axis to align on
elementsYesElement IDs to align

Elements are moved so their centers share the same coordinate on the specified axis.

distribute

Space elements evenly along an axis.

{
  "id": "c2",
  "type": "distribute",
  "axis": "x",
  "elements": ["icon1", "icon2", "icon3", "icon4"],
  "gap": 20
}
ParameterRequiredDescription
axisYes"x" or "y" - distribution direction
elementsYesElement IDs to distribute
gapNoPixel spacing between elements (default: 0)

First element stays in place. Subsequent elements are spaced evenly.

stack

Stack elements sequentially along one axis.

{
  "id": "c3",
  "type": "stack",
  "axis": "y",
  "elements": ["title", "description", "button"],
  "gap": 8
}
ParameterRequiredDescription
axisYes"x" or "y" - stacking direction
elementsYesElement IDs to stack
gapNoPixel spacing between elements (default: 0)

First element stays in place. Each subsequent element is positioned directly after the previous one.

grid

Arrange elements in a grid layout.

{
  "id": "c4",
  "type": "grid",
  "elements": ["a", "b", "c", "d", "e", "f"],
  "columns": 3,
  "columnGap": 16,
  "rowGap": 16
}
ParameterRequiredDescription
elementsYesElement IDs to arrange
columnsNoNumber of columns (default: 2)
rowsNoNumber of rows (optional)
columnGapNoHorizontal spacing (default: 0)
rowGapNoVertical spacing (default: 0)

Elements are laid out left-to-right, top-to-bottom. The first element’s position is the grid origin.

sameSize

Make elements the same dimensions.

{
  "id": "c5",
  "type": "sameSize",
  "elements": ["btn1", "btn2", "btn3"],
  "dimension": "width"
}
ParameterRequiredDescription
elementsYesElement IDs to resize
dimensionNo"width", "height", or "both" (default: "both")

The first element’s size is used as the reference.

contain

Expand a container to fit its child elements with padding.

{
  "id": "c6",
  "type": "contain",
  "containerId": "group1",
  "elements": ["node1", "node2", "node3"],
  "padding": 20
}
ParameterRequiredDescription
containerIdYesContainer element ID to resize
elementsYesChild element IDs that must fit inside
paddingNoPixel padding around children (default: 0)

The container is resized to the bounding box of all children, plus padding.

centerIn

Center elements inside a container.

{
  "id": "c7",
  "type": "centerIn",
  "containerId": "header",
  "elements": ["logo"],
  "axis": "both"
}
ParameterRequiredDescription
containerIdYesContainer element ID
elementsYesElement IDs to center
axisNo"x", "y", or "both" (default: "both")

minGap

Enforce minimum spacing between elements.

{
  "id": "c8",
  "type": "minGap",
  "axis": "y",
  "elements": ["item1", "item2", "item3"],
  "gap": 8
}
ParameterRequiredDescription
axisYes"x" or "y" - spacing direction
elementsYesElement IDs to check
gapYesMinimum pixel gap required

Elements that are closer than the minimum gap are pushed apart.

noOverlap

Prevent elements from overlapping.

{
  "id": "c9",
  "type": "noOverlap",
  "elements": ["label1", "label2", "label3"]
}
ParameterRequiredDescription
elementsYesElement IDs to check

Overlapping elements are shifted apart horizontally.

order

Hard ordering constraint enforced during auto-layout. Controls which rank (layer) a node lands on and its position within a rank.

{
  "id": "c10",
  "type": "order",
  "source": "db",
  "target": "api",
  "relation": "rightOf"
}
ParameterRequiredDescription
sourceYesElement ID of the source node
targetYesElement ID of the target node
relationYes"leftOf" | "rightOf" | "above" | "below" | "sameRank"

The relation describes the source relative to the target. For example, { source: "db", target: "api", relation: "rightOf" } places the database to the right of the API.

above and below control rank assignment (which layer a node lands in). leftOf and rightOf control position within the same rank. sameRank forces two nodes into the same layer.

Only applies to auto-laid-out nodes. Nodes with explicit layout positions are unaffected. Conflicting constraints (cycles) are detected and gracefully dropped rather than crashing the layout.

Adding constraints via operations

Use the addConstraint operation to add constraints to an existing scene:

{
  "op": "addConstraint",
  "constraint": {
    "id": "c1",
    "type": "align",
    "axis": "y",
    "elements": ["api", "db", "cache"]
  }
}

Use removeConstraint to remove:

{
  "op": "removeConstraint",
  "id": "c1"
}