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¶
- An explicit
height:on a layout tile always wins. - If the tile has no explicit height, chart-root
height:wins. - Chart-style
aspect_ratio:is used next (computesheight = width / aspect_ratio). - The theme default
style.charts.aspect_ratiois 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
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
Authoring Chart Size¶
Chart root holds the two fixed-geometry fields:
height: <px>— exact pixel height. Wins overaspect_ratioand theme defaults. Bypassesmin_height/max_heightclamps.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
Sidebar Layout¶
cols: - cols: # 66% main content - chart1 - chart2 - sidebar_chart # 33% sidebar
Header + Body + Footer¶
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:.
Related¶
- Boards Overview - Basic board structure
- Layouts - Layout types
- Examples - Complex layout patterns