Skip to content

Board Sizing

Dataface uses a three-layer sizing model. Understanding which layer owns what prevents most sizing surprises.


The Three Layers

Layer Where What it controls
Layout tile rows: / cols: / grid: entry The slot the chart renders into
Chart root charts.<name>.height A fixed height request from the chart itself
Chart style charts.<name>.style.aspect_ratio Aspect-ratio-derived height for this chart
Theme default style.charts.aspect_ratio in the face/theme cascade Global fallback

Priority

  1. An explicit height: on a layout tile always wins.
  2. If the tile has no explicit height, chart-root height: wins.
  3. Chart-style aspect_ratio: is used next (computes height = width / aspect_ratio).
  4. The theme default style.charts.aspect_ratio is the final fallback.

Width is always owned by the layout. The chart-root width: field is a label-overlap hint only — it does not affect the layout slot width.


Default Behavior

Width Rule

All items in a layout split the available width evenly: - In a cols layout with 2 items, each gets 50% - In a cols layout with 3 items, each gets 33.3%

Height Rule

Heights are derived from width ÷ aspect ratio for plot-style charts (bar, line, area, etc.). The global default aspect ratio is 1.5 (3:2), set in the base theme under style.charts.aspect_ratio. Override it in any face via style.charts.aspect_ratio or at the individual chart level with aspect_ratio:. Some chart types override this — for example, pie and arc default to 1.0 (square), and map types default to 1.2.

Exceptions — chart-root height is ignored for these types:

  • KPI — fixed compact height (renderer owns sizing)
  • Table — data-driven height based on actual row count
  • Callout — fixed compact height
  • Spark bar — fixed height

The aspect-ratio-derived height is clamped between min_height and max_height. The face/theme defaults are style.charts.min_height (150px) and style.charts.max_height (400px). Individual charts can override these clamps with per-chart style: {min_height: ..., max_height: ...} — see Chart height clamps below.

In a cols layout, all items share the same height (the tallest item's height).


Unequal Widths with Nesting

Use nested lists as a shorthand for nested boards. A nested list automatically inherits the layout type (rows or cols) of its parent.

50% / 25% / 25% Split

To make the first chart take up half the width (50%) and the next two share the remaining half (25% each), nest them in a list:

source: examples_db
title: "Asymmetric Layout"

queries:
  sales_by_category:
    sql: |
      SELECT category, SUM(revenue) AS revenue, SUM(units_sold) AS units_sold FROM ecommerce_orders GROUP BY category ORDER BY revenue DESC
  sales_summary:
    sql: |
      SELECT SUM(revenue) AS revenue, SUM(units_sold) AS units_sold, COUNT(DISTINCT category) AS category_count FROM ecommerce_orders

charts:
  main_chart:
    query: sales_by_category
    type: bar
    title: "Main Chart (50%)"
    x: category
    y: revenue
  kpi1:
    query: sales_summary
    type: kpi
    label: "Side Chart 1 (25%)"
    value: revenue
  kpi2:
    query: sales_summary
    type: kpi
    label: "Side Chart 2 (25%)"
    value: units_sold

# 50% / 25% / 25% split using nested cols
cols:
  - main_chart
  - cols:
      - kpi1
      - kpi2
Asymmetric Layout Asymmetric Layout DF-UNKNOWN-INTERNALChart Error: main_chartQuery execution failed: Source 'examples_db' not found. No source profiles are configured. Declare sources under `sources:` in your dataface.yml. (query: sales_by_category)https://docs.it-dataface.com/guides/error-handling/?code=DF-UNKNOWN-INTERNAL DF-UNKNOWN-INTERNALChart Error: kpi1Query execution failed: Source 'examples_db' not found. No source profiles are configured. Declare sources under `sources:` in your dataface.yml. (query: sales_summary)https://docs.it-dataface.com/guides/error-handling/?code=DF-UNKNOWN-INTERNALDF-UNKNOWN-INTERNALChart Error: kpi2Query execution failed: Source 'examples_db' not found. No source profiles are configured. Declare sources under `sources:` in your dataface.yml. (query: sales_summary)https://docs.it-dataface.com/guides/error-handling/?code=DF-UNKNOWN-INTERNAL 2026-07-17 15:04 UTC made with dataface

Complex Nesting

source: examples_db
title: "Complex Dashboard"

queries:
  sales_summary:
    sql: |
      SELECT SUM(revenue) AS revenue, SUM(units_sold) AS units_sold, COUNT(DISTINCT category) AS category_count FROM ecommerce_orders
  sales_by_category:
    sql: |
      SELECT category, SUM(revenue) AS revenue, SUM(units_sold) AS units_sold FROM ecommerce_orders GROUP BY category ORDER BY revenue DESC
  sales_by_product:
    sql: |
      SELECT product, category, SUM(revenue) AS revenue, SUM(units_sold) AS units_sold FROM ecommerce_orders GROUP BY product, category ORDER BY revenue DESC
  sales_by_date_category:
    sql: |
      SELECT date, category, SUM(revenue) AS revenue, SUM(units_sold) AS units_sold FROM ecommerce_orders GROUP BY date, category ORDER BY date, category

charts:
  kpi1:
    query: sales_summary
    type: kpi
    label: "Revenue"
    value: revenue
  kpi2:
    query: sales_summary
    type: kpi
    label: "Units Sold"
    value: units_sold
  mini1:
    query: sales_by_category
    type: bar
    title: "Mini Chart 1"
    x: category
    y: revenue
  mini2:
    query: sales_by_product
    type: bar
    title: "Mini Chart 2"
    x: product
    y: units_sold
  main:
    query: sales_by_date_category
    type: line
    title: "Main Analysis"
    x: date
    y: revenue
    color: category

rows:
  - cols:
      - kpi1
      - kpi2
      - cols:
          - mini1
          - mini2
  - main
Complex Dashboard Complex Dashboard DF-UNKNOWN-INTERNALChart Error: kpi1Query execution failed: Source 'examples_db' not found. No source profiles are configured. Declare sources under `sources:` in your dataface.yml. (query: sales_summary)https://docs.it-dataface.com/guides/error-handling/?code=DF-UNKNOWN-INTERNALDF-UNKNOWN-INTERNALChart Error: kpi2Query execution failed: Source 'examples_db' not found. No source profiles are configured. Declare sources under `sources:` in your dataface.yml. (query: sales_summary)https://docs.it-dataface.com/guides/error-handling/?code=DF-UNKNOWN-INTERNAL DF-UNKNOWN-INTERNALChart Error: mini1Query execution failed: Source 'examples_db' not found. No source profiles are configured. Declare sources under `sources:` in your dataface.yml. (query: sales_by_category)https://docs.it-dataface.com/guides/error-handling/?code=DF-UNKNOWN-INTERNALDF-UNKNOWN-INTERNALChart Error: mini2Query execution failed: Source 'examples_db' not found. No source profiles are configured. Declare sources under `sources:` in your dataface.yml. (query: sales_by_product)https://docs.it-dataface.com/guides/error-handling/?code=DF-UNKNOWN-INTERNAL DF-UNKNOWN-INTERNALChart Error: mainQuery execution failed: Source 'examples_db' not found. No source profiles are configured. Declare sources under `sources:` in your dataface.yml. (query: sales_by_date_category)https://docs.it-dataface.com/guides/error-handling/?code=DF-UNKNOWN-INTERNAL 2026-07-17 15:04 UTC made with dataface

Authoring Chart Size

Chart root holds the two fixed-geometry fields:

  • height: <px> — exact pixel height. Wins over aspect_ratio and theme defaults. Bypasses min_height / max_height clamps.
  • width: <px> — label-overlap hint only. Does not override the layout slot width.

style: holds aspect-ratio sizing fields (and all paint — colors, fonts, marks):

  • style.aspect_ratio: <float> — shape without a fixed pixel size. height = width / aspect_ratio.
  • style.min_height: <px> — floor for the computed height.
  • style.max_height: <px> — ceiling for the computed height.

height and width belong at chart root, not in style: — putting them there raises a validation error.

Choosing between chart-root height and a layout tile height

# Chart-root height — the chart requests 400px;
# the layout honours it unless the tile has its own height.
charts:
  inventory_overview:
    query: inventory
    type: bar
    x: category
    y: count
    height: 400
    style:
      palette: category10

# Layout tile height — the slot is fixed at 600px regardless of the chart inside.
rows:
  - height: 600
    rows:
      - inventory_overview

Use chart-root height when the chart itself has a natural size independent of its context (e.g. a detail chart that always needs 400px to be readable).

Use a layout tile height when you want the tile — and everything in that row — to be a fixed size (e.g. a KPI row that must be 120px tall).

Rejected shape

# REJECTED — height/width under style: is not supported
charts:
  bad:
    type: bar
    style:
      height: 400      # ← raises a validation error; move height to chart root

Explicit Sizing

Chart height

Set height on a chart to fix its pixel height explicitly. This bypasses aspect-ratio sizing and ignores min_height / max_height clamps.

charts:
  revenue:
    type: bar
    query: revenue_by_month
    x: month
    y: revenue
    height: 500   # fixed at 500px

Set aspect_ratio to control the shape without fixing an exact pixel size:

charts:
  revenue:
    type: bar
    query: revenue_by_month
    x: month
    y: revenue
    style:
      aspect_ratio: 2.5   # wider-than-default; height = width / 2.5

Chart height clamps

min_height and max_height cap the aspect-ratio-derived height. Face/theme defaults cascade from style.charts.min_height and style.charts.max_height. Override them per chart under style::

charts:
  stock_levels:
    type: bar
    query: stock_levels
    x: product_name
    y: stock_quantity
    style:
      aspect_ratio: 1.5
      min_height: 80    # floor for this chart only; overrides face/theme default
      max_height: 200   # ceiling for this chart only; overrides face/theme default

Explicit chart.height bypasses min_height / max_height — when you set an exact pixel height, the clamps do not apply.

Height on Rows

Set explicit height on row items:

rows:
  - height: "120px"
    cols:
      - kpi1
      - kpi2
      - kpi3

  - main_chart  # Takes remaining height

Grid Sizing

In grid layouts, use width and height on items:

grid:
  columns: 24
  items:
    - item: kpi1
      width: 8      # 8 of 24 columns
    - item: kpi2
      width: 8
    - item: main_chart
      width: 16
      height: 2     # 2 rows tall
    - item: sidebar
      width: 8
      height: 2

Sizing Patterns

KPI Row + Main Chart

rows:
  - height: "100px"
    cols: [kpi1, kpi2, kpi3]
  - main_chart
cols:
  - cols:           # 66% main content
      - chart1
      - chart2
  - sidebar_chart   # 33% sidebar
rows:
  - height: "80px"
    text: "# Dashboard Title"
  - main_content    # Flexible middle
  - height: "60px"
    text: "Footer text"

Configuration

Theme defaults (face/theme cascade)

These keys set the theme default layer — they apply to every chart that does not provide a chart-root override.

Key Default Description
style.charts.aspect_ratio 1.5 Global width:height ratio for plot-style charts
style.charts.min_height 150 Minimum chart height (px) when aspect-ratio drives sizing
style.charts.max_height 400 Maximum chart height (px) when aspect-ratio drives sizing
style.charts.<type>.aspect_ratio Per-type override (e.g. pie: 1.0, map: 1.2)

height and width cannot be set in the theme — they are per-chart explicit overrides only (see below).

Chart-root fields (per chart, under charts.<name>:)

Field Description
height Exact pixel height. Wins over aspect_ratio and theme. Bypasses min_height/max_height.
width Width hint in pixels. Feeds the label-overlap heuristic; does not override the layout slot width.

Per-chart style fields (under charts.<name>.style: or in the theme under style.charts.*)

Field Description
aspect_ratio Shape without a fixed pixel size. height = width / aspect_ratio.
min_height Floor for this chart only; overrides theme style.charts.min_height.
max_height Ceiling for this chart only; overrides theme style.charts.max_height.

aspect_ratio, min_height, and max_height are valid both at chart level (style: {aspect_ratio: 2.0}) and in the theme (style.charts.aspect_ratio). height and width are chart-root-only — they are not valid under style:.