OPF
SpecAuthoring schema referenceView source

Slide Layout

Schema for slide-layout records. A layout is one ordered list of regions, declared once, in reading order: 'direction' says whether the record's 'regions' sit side by side (row) or are stacked (column), and each region says which content kinds it takes and how several blocks share it. A split is an entry that nests a second list the other way, which is how a layout gets two dimensions. 'title' and 'subtitle' are reserved heading regions. Engines compile the list into a grid of tracks (the guillotine partition it describes). Slide content stays flat: engines bind a slide's blocks to the regions by reading order, role and kind (bindRegions in @openpresentation/opf), a block may pin itself to a region with 'region', and an empty region collapses into a neighbour. Built-in and custom layouts are records of this one schema; a custom layout is embedded under catalogs.custom.layouts or shipped in a catalog. Documents reference a layout from Slide.layout; a slide without a layout, with layout 'auto', or whose layout resolves nowhere composes automatically. A document references a record as a bare id or 'name:id' and resolves it in its own catalogs groups first, then in the catalog the host registered for the group's source; engines never fetch a catalog. A published record file carries '$schema' and 'id'; the copy a document embeds under catalogs.<group>.<kind>.<id> carries neither (the key is the id) and no 'x-*' display metadata.

Define a slide layout

A layout is a reusable record: one ordered list of regions, declared once, in reading order.direction places them side by side (row) or stacked (column), a region'ssize is its share, and accepts says what content it takes. title is the reserved heading region. A slide selects the record with layout: "text".

Text layout (Gallery)
{
  "$schema": "https://openpresentation.org/schema/opf-layout/v2",
  "id": "text",
  "name": "Text",
  "summary": "Prose. Several blocks sit side by side when short and stack when long.",
  "tags": [
    "Text"
  ],
  "direction": "column",
  "regions": [
    {
      "name": "title"
    },
    {
      "name": "body",
      "accepts": [
        "text",
        "list",
        "quote",
        "code",
        "group"
      ],
      "role": "primary",
      "flow": "auto"
    }
  ],
  "description": "Explain one idea in continuous prose. Use paragraphs or flowing blocks for detail that needs to be read in sequence.",
  "preview": {
    "vectorSrc": "https://www.pptx.gallery/layout-previews/text.svg"
  }
}

Browse layout records, or embed your own under catalogs.custom.layouts.

Schema $id
https://openpresentation.org/schema/opf-layout/v2
Type
object
Source
spec/schemas/layout.schema.json
Fields
13 · 4 required

Field index

FieldTypeReq.DefaultDescription
$schemaconstyes—Identifies a published record file as a layout template. Required in a published file; an embedded copy omits it.
$schema · Allowed values
"https://openpresentation.org/schema/opf-layout/v2"
idrestrictionyes—The layout's id in its catalog, lowercase kebab-case. Required in a published record file; a document references the record by it (a bare id, or 'name:id' for a named group) and embeds it keyed by it, without this field. 'auto' is reserved: Slide.layout 'auto' is automatic composition, so no catalog may define a layout of that id.
namestringyes—Human-readable layout name, shown in layout pickers and as the PowerPoint layout name.
summarystring——One-sentence positioning of the layout — when to reach for it.
descriptionstring——Longer prose describing the layout structure and ideal use cases.
designref:DesignHints——The layout's design defaults, with the same keys and values as the deck's design and a slide's design (a slide overrides exactly what its layout sets, by the same name). An absent key means the layout has no opinion. Per key the slide's design wins, then the deck's design, then the resolved theme's design, then this record's design, then the engine default. Composition, the renderer and the PPTX exporter all read the one result.
directionenum——How the record's 'regions' are laid out: 'row' places them side by side, left to right in reading order; 'column' stacks them top to bottom. Default 'column'.
direction · Allowed values
"row""column"
anchorenum——Vertical position of the content of every body region when it is shorter than the region. A split's 'anchor' replaces it for the regions under that split, and a region's own 'anchor' replaces both. Only 'anchor' is inherited, and only by body regions: the heading regions 'title' and 'subtitle' never take it, and the other region rules stay per region. One exception places the whole slide: when the record is a column and every entry of its 'regions' list is sized 'auto' (heading regions included), the record has no numeric row to hold the leftover height, so its 'anchor' places the whole stack, title and subtitle included, in the content box's leftover height: 'middle' centres it, 'bottom' sits it at the foot, 'top' (default) starts it at the top as before. A record with any numeric entry, a row record and an anchor on a split keep the rule above. Default 'top'.
anchor · Allowed values
"top""middle""bottom"
regionsarray<ref:RegionEntry>yes—The record's regions in reading order: 1 to 12 entries, each a region ({ name, size?, ...rules }) or a split ({ direction, regions, size?, anchor? }). Every region is declared once, here, with its content rules; a block can target a body region with 'region': '<name>'. Names are unique across the whole record. 'size' is a number above 0 and up to 100 (default 1) that siblings share in proportion, separated by the gap; 'auto' is the height the content needs, allowed only in a column. 'title' and 'subtitle' are heading regions that take only a size (default auto in a column, 1 in a row): 'title' holds the slide's heading group (tag, title and subtitle, stacked) and a 'subtitle' region takes the subtitle out of it, and a 'subtitle' needs a 'title'. A record with no 'title' region gets an implicit auto row on top for a slide that has headings. Splits nest at most three levels (the record's own list is level 1). Rules the schema cannot express (a reserved or repeated name, a 'subtitle' without a 'title', 'auto' outside a column, nesting too deep, more than 12 rows or columns once compiled) are the validate findings opf/layout-template and opf/layout-region.
overflowRegionstring——The region where content that no region accepts goes, whatever its 'accepts', while it has room; content beyond every region's room is drawn there too, with the warning opf/layout-unplaced. Omitted: the first primary region (in reading order) whose flow is not 'none'.
tagsarray<string>——Free-form labels for filtering and search.
previewobject——Visual previews of the record, used by picker UIs and inline rendering. All sub-fields are optional; engines fall back gracefully when previews aren't available.
compositionref:Composition——Only 'gap', 'padding', 'minFontSize' and 'overflow', with their 0.18 meaning. A template's regions replace composition.mode, columns and weights.

$schema

typeconstrequiredyesdefault—

Identifies a published record file as a layout template. Required in a published file; an embedded copy omits it.

$schema · Allowed values
"https://openpresentation.org/schema/opf-layout/v2"
$schema.json
{
  "$schema": "https://openpresentation.org/schema/opf-layout/v2"
}

id

typerestrictionrequiredyesdefault—pattern^[a-z][a-z0-9-]*$

The layout's id in its catalog, lowercase kebab-case. Required in a published record file; a document references the record by it (a bare id, or 'name:id' for a named group) and embeds it keyed by it, without this field. 'auto' is reserved: Slide.layout 'auto' is automatic composition, so no catalog may define a layout of that id.

id.json
{
  "id": "cover"
}

name

typestringrequiredyesdefault—

Human-readable layout name, shown in layout pickers and as the PowerPoint layout name.

name.json
{
  "name": "Cover"
}

summary

typestringrequirednodefault—

One-sentence positioning of the layout — when to reach for it.

summary.json
{
  "summary": "Two to six ideas of equal weight, as cards."
}

description

typestringrequirednodefault—

Longer prose describing the layout structure and ideal use cases.

description.json
{
  "description": "Two equal-width columns under a left-aligned slide title. Use when comparing two ideas, before/after pairs, or paired text + image content."
}

design

typeref:DesignHintsrequirednodefault—

The layout's design defaults, with the same keys and values as the deck's design and a slide's design (a slide overrides exactly what its layout sets, by the same name). An absent key means the layout has no opinion. Per key the slide's design wins, then the deck's design, then the resolved theme's design, then this record's design, then the engine default. Composition, the renderer and the PPTX exporter all read the one result.

design.titleAlignment · Allowed values
"left""center""right"
design.contentAlignment · Allowed values
"left""center""right"
design.contentDirection · Allowed values
"horizontal""vertical"
design.chartPrimary · Allowed values
"none""top""bottom""left""right"
design.imageFit · Allowed values
"cover""contain""stretch"
design.listBullet · Allowed values
"character""image""none"

direction

typeenumrequirednodefault—

How the record's 'regions' are laid out: 'row' places them side by side, left to right in reading order; 'column' stacks them top to bottom. Default 'column'.

direction · Allowed values
"row""column"
direction.json
{
  "direction": "row"
}

anchor

typeenumrequirednodefault—

Vertical position of the content of every body region when it is shorter than the region. A split's 'anchor' replaces it for the regions under that split, and a region's own 'anchor' replaces both. Only 'anchor' is inherited, and only by body regions: the heading regions 'title' and 'subtitle' never take it, and the other region rules stay per region. One exception places the whole slide: when the record is a column and every entry of its 'regions' list is sized 'auto' (heading regions included), the record has no numeric row to hold the leftover height, so its 'anchor' places the whole stack, title and subtitle included, in the content box's leftover height: 'middle' centres it, 'bottom' sits it at the foot, 'top' (default) starts it at the top as before. A record with any numeric entry, a row record and an anchor on a split keep the rule above. Default 'top'.

anchor · Allowed values
"top""middle""bottom"
anchor.json
{
  "anchor": "top"
}

regions

typearray<ref:RegionEntry>requiredyesdefault—

The record's regions in reading order: 1 to 12 entries, each a region ({ name, size?, ...rules }) or a split ({ direction, regions, size?, anchor? }). Every region is declared once, here, with its content rules; a block can target a body region with 'region': '<name>'. Names are unique across the whole record. 'size' is a number above 0 and up to 100 (default 1) that siblings share in proportion, separated by the gap; 'auto' is the height the content needs, allowed only in a column. 'title' and 'subtitle' are heading regions that take only a size (default auto in a column, 1 in a row): 'title' holds the slide's heading group (tag, title and subtitle, stacked) and a 'subtitle' region takes the subtitle out of it, and a 'subtitle' needs a 'title'. A record with no 'title' region gets an implicit auto row on top for a slide that has headings. Splits nest at most three levels (the record's own list is level 1). Rules the schema cannot express (a reserved or repeated name, a 'subtitle' without a 'title', 'auto' outside a column, nesting too deep, more than 12 rows or columns once compiled) are the validate findings opf/layout-template and opf/layout-region.

regions[] (oneOf 1).name · Allowed values
"title", "subtitle"
regions[] (oneOf 1).size · Named choices (see schema for other values and constraints)
"auto"
regions[] (oneOf 2).size · Named choices (see schema for other values and constraints)
"auto"
regions[] (oneOf 2).accepts[] · Allowed values
"text", "list", "image", "video", "chart", "table", "code", "metric", "quote", "timeline", "group"
regions[] (oneOf 2).role · Allowed values
"primary", "secondary", "media", "supporting"
regions[] (oneOf 2).flow · Allowed values
"none", "grid", "column", "auto"
regions[] (oneOf 2).listColumns · Allowed values
"auto", 1
regions[] (oneOf 2).anchor · Allowed values
"top", "middle", "bottom"
regions[] (oneOf 2).empty · Allowed values
"collapse", "keep"
regions[] (oneOf 3).direction · Allowed values
"row", "column"
regions[] (oneOf 3).size · Named choices (see schema for other values and constraints)
"auto"
regions[] (oneOf 3).anchor · Allowed values
"top", "middle", "bottom"
regions.json
{
  "regions": [
    {
      "name": "main",
      "size": 2,
      "accepts": [
        "text"
      ]
    },
    {
      "name": "aside",
      "size": 1,
      "accepts": [
        "metric"
      ]
    }
  ]
}

overflowRegion

typestringrequirednodefault—pattern^[a-z][a-z0-9-]*$

The region where content that no region accepts goes, whatever its 'accepts', while it has room; content beyond every region's room is drawn there too, with the warning opf/layout-unplaced. Omitted: the first primary region (in reading order) whose flow is not 'none'.

tags

typearray<string>requirednodefault—

Free-form labels for filtering and search.

tags.json
{
  "tags": [
    "title",
    "minimal"
  ]
}

preview

typeobjectrequirednodefault—

Visual previews of the record, used by picker UIs and inline rendering. All sub-fields are optional; engines fall back gracefully when previews aren't available.

composition

typeref:Compositionrequirednodefault—

Only 'gap', 'padding', 'minFontSize' and 'overflow', with their 0.18 meaning. A template's regions replace composition.mode, columns and weights.

composition.overflow · Allowed values
"warn""error"
Complete definition constraints
Schema constraints
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://openpresentation.org/schema/opf-layout/v2",
  "$comment": "The v2 in the $id marks the pre-1.0 line of this schema, not a frozen contract: it may change in any 0.x minor release. The release that produced this copy is the version of the @openpresentation/opf package it came from (opf --version; opf schemas lists it next to each id). See docs/schema-versioning.md.",
  "title": "Slide Layout",
  "description": "Schema for slide-layout records. A layout is one ordered list of regions, declared once, in reading order: 'direction' says whether the record's 'regions' sit side by side (row) or are stacked (column), and each region says which content kinds it takes and how several blocks share it. A split is an entry that nests a second list the other way, which is how a layout gets two dimensions. 'title' and 'subtitle' are reserved heading regions. Engines compile the list into a grid of tracks (the guillotine partition it describes). Slide content stays flat: engines bind a slide's blocks to the regions by reading order, role and kind (bindRegions in @openpresentation/opf), a block may pin itself to a region with 'region', and an empty region collapses into a neighbour. Built-in and custom layouts are records of this one schema; a custom layout is embedded under catalogs.custom.layouts or shipped in a catalog. Documents reference a layout from Slide.layout; a slide without a layout, with layout 'auto', or whose layout resolves nowhere composes automatically.\n\nA document references a record as a bare id or 'name:id' and resolves it in its own catalogs groups first, then in the catalog the host registered for the group's source; engines never fetch a catalog. A published record file carries '$schema' and 'id'; the copy a document embeds under catalogs.<group>.<kind>.<id> carries neither (the key is the id) and no 'x-*' display metadata.",
  "type": "object",
  "required": [
    "$schema",
    "id",
    "name",
    "regions"
  ],
  "properties": {
    "$schema": {
      "type": "string",
      "const": "https://openpresentation.org/schema/opf-layout/v2",
      "description": "Identifies a published record file as a layout template. Required in a published file; an embedded copy omits it."
    },
    "id": {
      "type": "string",
      "pattern": "^[a-z][a-z0-9-]*$",
      "description": "The layout's id in its catalog, lowercase kebab-case. Required in a published record file; a document references the record by it (a bare id, or 'name:id' for a named group) and embeds it keyed by it, without this field. 'auto' is reserved: Slide.layout 'auto' is automatic composition, so no catalog may define a layout of that id.",
      "examples": [
        "cover",
        "pillars",
        "chart-beside",
        "roadmap-split"
      ],
      "not": {
        "const": "auto"
      }
    },
    "name": {
      "type": "string",
      "description": "Human-readable layout name, shown in layout pickers and as the PowerPoint layout name.",
      "examples": [
        "Cover",
        "Pillars",
        "Chart beside"
      ]
    },
    "summary": {
      "type": "string",
      "description": "One-sentence positioning of the layout — when to reach for it.",
      "examples": [
        "Two to six ideas of equal weight, as cards.",
        "A chart with the takeaway beside it."
      ]
    },
    "description": {
      "type": "string",
      "description": "Longer prose describing the layout structure and ideal use cases.",
      "examples": [
        "Two equal-width columns under a left-aligned slide title. Use when comparing two ideas, before/after pairs, or paired text + image content."
      ]
    },
    "design": {
      "$ref": "#/$defs/DesignHints",
      "description": "The layout's design defaults, with the same keys and values as the deck's design and a slide's design (a slide overrides exactly what its layout sets, by the same name). An absent key means the layout has no opinion. Per key the slide's design wins, then the deck's design, then the resolved theme's design, then this record's design, then the engine default. Composition, the renderer and the PPTX exporter all read the one result."
    },
    "direction": {
      "type": "string",
      "enum": [
        "row",
        "column"
      ],
      "description": "How the record's 'regions' are laid out: 'row' places them side by side, left to right in reading order; 'column' stacks them top to bottom. Default 'column'.",
      "examples": [
        "row",
        "column"
      ]
    },
    "anchor": {
      "type": "string",
      "enum": [
        "top",
        "middle",
        "bottom"
      ],
      "description": "Vertical position of the content of every body region when it is shorter than the region. A split's 'anchor' replaces it for the regions under that split, and a region's own 'anchor' replaces both. Only 'anchor' is inherited, and only by body regions: the heading regions 'title' and 'subtitle' never take it, and the other region rules stay per region. One exception places the whole slide: when the record is a column and every entry of its 'regions' list is sized 'auto' (heading regions included), the record has no numeric row to hold the leftover height, so its 'anchor' places the whole stack, title and subtitle included, in the content box's leftover height: 'middle' centres it, 'bottom' sits it at the foot, 'top' (default) starts it at the top as before. A record with any numeric entry, a row record and an anchor on a split keep the rule above. Default 'top'."
    },
    "regions": {
      "type": "array",
      "minItems": 1,
      "maxItems": 12,
      "items": {
        "$ref": "#/$defs/RegionEntry"
      },
      "description": "The record's regions in reading order: 1 to 12 entries, each a region ({ name, size?, ...rules }) or a split ({ direction, regions, size?, anchor? }). Every region is declared once, here, with its content rules; a block can target a body region with 'region': '<name>'. Names are unique across the whole record. 'size' is a number above 0 and up to 100 (default 1) that siblings share in proportion, separated by the gap; 'auto' is the height the content needs, allowed only in a column. 'title' and 'subtitle' are heading regions that take only a size (default auto in a column, 1 in a row): 'title' holds the slide's heading group (tag, title and subtitle, stacked) and a 'subtitle' region takes the subtitle out of it, and a 'subtitle' needs a 'title'. A record with no 'title' region gets an implicit auto row on top for a slide that has headings. Splits nest at most three levels (the record's own list is level 1). Rules the schema cannot express (a reserved or repeated name, a 'subtitle' without a 'title', 'auto' outside a column, nesting too deep, more than 12 rows or columns once compiled) are the validate findings opf/layout-template and opf/layout-region.",
      "examples": [
        [
          {
            "name": "main",
            "size": 2,
            "accepts": [
              "text"
            ]
          },
          {
            "name": "aside",
            "size": 1,
            "accepts": [
              "metric"
            ]
          }
        ],
        [
          {
            "name": "title"
          },
          {
            "direction": "row",
            "regions": [
              {
                "name": "first",
                "accepts": [
                  "text"
                ]
              },
              {
                "name": "second",
                "accepts": [
                  "text"
                ]
              }
            ]
          }
        ]
      ]
    },
    "overflowRegion": {
      "type": "string",
      "pattern": "^[a-z][a-z0-9-]*$",
      "description": "The region where content that no region accepts goes, whatever its 'accepts', while it has room; content beyond every region's room is drawn there too, with the warning opf/layout-unplaced. Omitted: the first primary region (in reading order) whose flow is not 'none'."
    },
    "tags": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Free-form labels for filtering and search.",
      "examples": [
        [
          "title",
          "minimal"
        ],
        [
          "chart",
          "kpi"
        ],
        [
          "two-column",
          "comparison"
        ]
      ]
    },
    "preview": {
      "type": "object",
      "description": "Visual previews of the record, used by picker UIs and inline rendering. All sub-fields are optional; engines fall back gracefully when previews aren't available.",
      "properties": {
        "src": {
          "type": "string",
          "format": "uri",
          "description": "Main preview image (PNG/JPG). Used as the primary visual in picker UIs and previews of the record.",
          "examples": [
            "https://example.com/layouts/cover.png"
          ]
        },
        "thumbnailSrc": {
          "type": "string",
          "format": "uri",
          "description": "Smaller thumbnail preview suited to dense grid views.",
          "examples": [
            "https://example.com/layouts/cover.thumbnail.png"
          ]
        },
        "vectorSrc": {
          "type": "string",
          "format": "uri",
          "description": "SVG / vector preview for crisp scaling at any size.",
          "examples": [
            "https://www.pptx.gallery/layout-previews/cover.svg"
          ]
        }
      }
    },
    "composition": {
      "type": "object",
      "description": "Only 'gap', 'padding', 'minFontSize' and 'overflow', with their 0.18 meaning. A template's regions replace composition.mode, columns and weights.",
      "$ref": "#/$defs/Composition"
    }
  },
  "patternProperties": {
    "^x-": {}
  },
  "additionalProperties": false,
  "$defs": {
    "RegionEntry": {
      "description": "One entry of a regions list: a heading region, a body region or a split.",
      "oneOf": [
        {
          "$ref": "#/$defs/HeadingRegion"
        },
        {
          "$ref": "#/$defs/Region"
        },
        {
          "$ref": "#/$defs/Split"
        }
      ]
    },
    "RegionSize": {
      "oneOf": [
        {
          "type": "number",
          "exclusiveMinimum": 0,
          "maximum": 100
        },
        {
          "const": "auto"
        }
      ],
      "description": "The region's or split's share along its parent's direction: a number above 0 and up to 100 that siblings share in proportion (the gap is taken out first), default 1; or 'auto', the length the content needs at the starting text size (up to the space the heading rows and the content of the numeric rows leave; auto rows that do not all fit shrink together, each giving up the same fraction of what it can give up above its content's length at the minimum font size; a split sized auto is as tall as its tallest content, and every row of a column split sized auto is auto too; auto regions with no content take no space). 'auto' is allowed only on an entry of a column; in a row it is the validate finding opf/layout-template. When every entry of a column record is 'auto', the record's 'anchor' places the whole stack. The default for a heading region is 'auto' in a column and 1 in a row.",
      "examples": [
        1,
        2,
        "auto"
      ]
    },
    "HeadingRegion": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "name"
      ],
      "description": "A reserved heading region: 'title' holds the slide's heading group (tag, title and subtitle, stacked) and 'subtitle' takes the subtitle out of it. A heading region takes only a size. At most one of each; a 'subtitle' needs a 'title'.",
      "properties": {
        "name": {
          "type": "string",
          "enum": [
            "title",
            "subtitle"
          ],
          "description": "'title' or 'subtitle'."
        },
        "size": {
          "$ref": "#/$defs/RegionSize"
        }
      }
    },
    "Split": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "direction",
        "regions"
      ],
      "description": "A split nests a list of regions the other way inside one cell of its parent: a row of regions inside a column, or a column inside a row. It has no name; its regions are declared in reading order like the record's own. Splits nest at most three levels (the record's own list is level 1).",
      "properties": {
        "direction": {
          "type": "string",
          "enum": [
            "row",
            "column"
          ],
          "description": "How the split's 'regions' are laid out: 'row' side by side, 'column' stacked."
        },
        "regions": {
          "type": "array",
          "minItems": 1,
          "maxItems": 12,
          "items": {
            "$ref": "#/$defs/RegionEntry"
          },
          "description": "The split's regions in reading order: 1 to 12 regions and splits."
        },
        "size": {
          "$ref": "#/$defs/RegionSize"
        },
        "anchor": {
          "type": "string",
          "enum": [
            "top",
            "middle",
            "bottom"
          ],
          "description": "Vertical position of the content of every body region under this split, unless the region sets its own. The heading regions 'title' and 'subtitle' never inherit it."
        }
      }
    },
    "Region": {
      "type": "object",
      "additionalProperties": false,
      "description": "One body region of a layout: its name, its share of the space and the rules for which content it takes and how several blocks share it.",
      "properties": {
        "name": {
          "type": "string",
          "pattern": "^[a-z][a-z0-9-]*$",
          "not": {
            "enum": [
              "title",
              "subtitle"
            ]
          },
          "description": "The region's name, lowercase kebab-case, unique across the whole record. A block targets it with 'region': '<name>'. It may not be 'title' (those are heading regions), 'tag', 'auto' or one of the promoted-region words ('left', 'center', 'right', 'top', 'middle', 'bottom'), so a Markdown block's region= option stays unambiguous: the validate finding opf/layout-region.",
          "examples": [
            "main",
            "aside",
            "chart"
          ]
        },
        "size": {
          "$ref": "#/$defs/RegionSize"
        },
        "accepts": {
          "type": "array",
          "minItems": 1,
          "uniqueItems": true,
          "items": {
            "type": "string",
            "enum": [
              "text",
              "list",
              "image",
              "video",
              "chart",
              "table",
              "code",
              "metric",
              "quote",
              "timeline",
              "group"
            ]
          },
          "description": "Content kinds the region takes: the body content kinds, and 'group' for a content group of any content. A group is also accepted where every one of its leaf kinds is. Omitted: every body content kind and 'group'.",
          "examples": [
            [
              "text",
              "list"
            ],
            [
              "image",
              "video"
            ]
          ]
        },
        "role": {
          "type": "string",
          "enum": [
            "primary",
            "secondary",
            "media",
            "supporting"
          ],
          "description": "Which content the region wants first. Binding gives a picture (image, video) to a media region first, then primary, secondary, supporting; every other kind to a primary region first, then secondary, supporting, media; of two equal regions the first in reading order fills first. A supporting region receives content only when no primary or secondary region that accepts it has room, or by a pin. Default 'primary'."
        },
        "flow": {
          "type": "string",
          "enum": [
            "none",
            "grid",
            "column",
            "auto"
          ],
          "description": "How several blocks share the region: 'none' one block fills it; 'grid' by count (1 fills, 2 side by side, 3 in a row, 4 as 2 x 2, 5 as 3 + 2, 6 as 3 x 2, 7 to 12 in four columns; rows and columns swap in a portrait region; a short last row is centred); 'column' stacked at the heights the blocks need, one gap apart, and placed by the region's anchor (charts, pictures, tables, timelines and videos take what the measured blocks leave; blocks that do not fit share the region, each giving up the same fraction of what it can give up above its height at the minimum font size); 'auto' a grid when every block is short and a column when any block is long (more than 6 estimated lines in its grid cell at the starting size). design.contentDirection turns every flowing region into one row or one column. Default 'auto'."
        },
        "max": {
          "type": "integer",
          "minimum": 1,
          "maximum": 12,
          "description": "Blocks the region holds on one slide. Default 1 for flow 'none' (which requires 1), else 6. Content beyond every region's room is drawn in the overflow region with the warning opf/layout-unplaced, and paginate moves it to a continuation slide."
        },
        "bleed": {
          "type": "boolean",
          "description": "The region's outer edges that lie on the content box's edge extend to the slide edge, as a placed image does. A bled region is never drawn as a card. Default false."
        },
        "listColumns": {
          "oneOf": [
            {
              "const": "auto"
            },
            {
              "const": 1
            }
          ],
          "description": "'auto': a list in the region that does not fit its cell at the starting size (a lone list, or one of several blocks) flows into up to three columns before it shrinks, as a list payload's columns: 'auto'. Default 1."
        },
        "anchor": {
          "type": "string",
          "enum": [
            "top",
            "middle",
            "bottom"
          ],
          "description": "Vertical position of the region's content when it is shorter than the region. Replaces the 'anchor' of the record and of the splits around it. Default: the nearest of those that sets one, else 'top'. A picture shown whole (fit 'contain') and a video, whose 16:9 frame is the largest that fits the cell, sit at the anchor inside the cell."
        },
        "empty": {
          "type": "string",
          "enum": [
            "collapse",
            "keep"
          ],
          "description": "What the region does on a slide that gives it no content: 'collapse' (default) joins its cells to a neighbouring area that shares the full length of one of its edges and is not itself empty; 'keep' leaves the space."
        }
      },
      "required": [
        "name"
      ]
    },
    "DesignHints": {
      "type": "object",
      "additionalProperties": false,
      "description": "Design hints a layout carries. The keys and lowercase values are those of the deck's design and a slide's design in opf.schema.json (Design), so a slide overrides a layout by the same name and layout.design can be copied into slide.design unchanged. An absent key means the layout has no opinion. Only the keys the layout sets are stored. scripts/check-spec-integrity.mjs verifies that every key here has the same type and values as its Design counterpart.",
      "properties": {
        "titleAlignment": {
          "type": "string",
          "enum": [
            "left",
            "center",
            "right"
          ],
          "description": "Horizontal alignment of the title heading area."
        },
        "contentAlignment": {
          "type": "string",
          "enum": [
            "left",
            "center",
            "right"
          ],
          "description": "Horizontal alignment of the body regions."
        },
        "contentBox": {
          "type": "boolean",
          "description": "Whether the body regions are drawn inside a visible card or surface."
        },
        "contentDirection": {
          "type": "string",
          "enum": [
            "horizontal",
            "vertical"
          ],
          "description": "Axis along which parallel body content is arranged: 'vertical' is a column, 'horizontal' a row. On a layout slide it turns every flowing region into one row or one column; the slide's own composition.mode, columns and weights rank above it."
        },
        "chartPrimary": {
          "type": "string",
          "enum": [
            "none",
            "top",
            "bottom",
            "left",
            "right"
          ],
          "description": "Where the primary chart sits relative to supporting content on automatic slides. Template layouts express this arrangement with their regions; chartPrimary does not override a template."
        },
        "imageFit": {
          "type": "string",
          "enum": [
            "cover",
            "contain",
            "stretch"
          ],
          "description": "Default fit of the slide's image blocks: 'cover' fills the frame and crops around focus, 'contain' shows the whole picture, 'stretch' scales it to the frame."
        },
        "listBullet": {
          "type": "string",
          "enum": [
            "character",
            "image",
            "none"
          ],
          "description": "Marker style of lists: 'character' draws the glyph, 'image' draws the deck's icon logo as a picture bullet, 'none' draws no marker and no hanging indent (label-and-description lists)."
        },
        "mirror": {
          "type": "boolean",
          "description": "Draw the layout mirrored: each row's cells and the column sizes reversed, so a 'beside' layout puts its picture, chart or table at the end. Logical: a right-to-left deck mirrors on top. Binding and reading order do not change."
        }
      }
    },
    "Composition": {
      "type": "object",
      "additionalProperties": false,
      "description": "A template's composition: only gap, padding, minFontSize and overflow, with their 0.18 meaning. A slide's composition overrides them; a slide's composition.mode, columns and weights arrange its first primary flowing region.",
      "properties": {
        "gap": {
          "type": "number",
          "minimum": 0,
          "maximum": 0.1,
          "description": "Space between cells as a fraction of the container short edge (canvas at slide root). Default 0.03333333333333333."
        },
        "padding": {
          "type": "number",
          "minimum": 0,
          "maximum": 0.2,
          "description": "Inset as a fraction of the container short edge. Default 0.08 on a slide, 0 inside a group."
        },
        "minFontSize": {
          "type": "number",
          "minimum": 8,
          "maximum": 32,
          "description": "Minimum readable text size in reference pixels at a 720-pixel canvas short edge. Default 16. Overflow is diagnosed when text cannot fit at this size."
        },
        "overflow": {
          "type": "string",
          "enum": [
            "warn",
            "error"
          ],
          "description": "warn returns diagnostics for content that does not fit; error rejects layout. Content is never silently removed. Default warn."
        }
      }
    }
  }
}

Definition choices

Values declared by this schema and its nested definitions. Paths ending in [] describe array items; * describes each dictionary entry. Variant paths apply within the named schema branch.

$defs.RegionSize · Named choices (see schema for other values and constraints)
"auto"
$defs.HeadingRegion.name · Allowed values
"title", "subtitle"
$defs.HeadingRegion.size · Named choices (see schema for other values and constraints)
"auto"
$defs.Split.direction · Allowed values
"row", "column"
$defs.Split.size · Named choices (see schema for other values and constraints)
"auto"
$defs.Split.anchor · Allowed values
"top", "middle", "bottom"
$defs.Region.size · Named choices (see schema for other values and constraints)
"auto"
$defs.Region.accepts[] · Allowed values
"text", "list", "image", "video", "chart", "table", "code", "metric", "quote", "timeline", "group"
$defs.Region.role · Allowed values
"primary", "secondary", "media", "supporting"
$defs.Region.flow · Allowed values
"none", "grid", "column", "auto"
$defs.Region.listColumns · Allowed values
"auto", 1
$defs.Region.anchor · Allowed values
"top", "middle", "bottom"
$defs.Region.empty · Allowed values
"collapse", "keep"
$defs.DesignHints.titleAlignment · Allowed values
"left", "center", "right"
$defs.DesignHints.contentAlignment · Allowed values
"left", "center", "right"
$defs.DesignHints.contentDirection · Allowed values
"horizontal", "vertical"
$defs.DesignHints.chartPrimary · Allowed values
"none", "top", "bottom", "left", "right"
$defs.DesignHints.imageFit · Allowed values
"cover", "contain", "stretch"
$defs.DesignHints.listBullet · Allowed values
"character", "image", "none"
$defs.Composition.overflow · Allowed values
"warn", "error"