Malloy supports model-level annotations (using ##) that configure rendering defaults across an entire model. These are set at the top of a file, outside any source or query.
Chart Defaults
Use ## viz.<chart_type>.defaults.* to set default properties for all charts of a given type in the model. Individual charts can still override these defaults.
In this example, all line charts default to independent y-axes. The third nested chart explicitly overrides back to shared axes:
## viz.line_chart.defaults.y.independent=true source: flights is duckdb.table('../data/flights.parquet') extend { join_one: carriers is duckdb.table('../data/carriers.parquet') on carrier = carriers.code measure: flight_count is count() aircraft_count is count(tail_num) }
run: flights -> { group_by: carriers.nickname aggregate: flight_count // This chart inherits y.independent=true from the model default # line_chart nest: default_independent is { group_by: dep_month is dep_time.month aggregate: flight_count limit: 12 } // This chart explicitly overrides back to shared axes # line_chart { y.independent=false } nest: shared_axes is { group_by: dep_month is dep_time.month aggregate: flight_count limit: 12 } limit: 3 }
[ { "nickname": "Southwest", "flight_count": 88751, "default_independent": [ { "dep_month": "2005-12-01T00:00:00.000Z", "flight_count": 1606 }, { "dep_month": "2005-11-01T00:00:00.000Z", "flight_count": 1448 }, { "dep_month": "2005-10-01T00:00:00.000Z", "flight_count": 1543 }, { "dep_month": "2005-09-01T00:00:00.000Z", "flight_count": 1466 }, { "dep_month": "2005-08-01T00:00:00.000Z", "flight_count": 1582 }, { "dep_month": "2005-07-01T00:00:00.000Z", "flight_count": 1564 }, { "dep_month": "2005-06-01T00:00:00.000Z", "flight_count": 1383 }, { "dep_month": "2005-05-01T00:00:00.000Z", "flight_count": 1384 }, { "dep_month": "2005-04-01T00:00:00.000Z", "flight_count": 1432 }, { "dep_month": "2005-03-01T00:00:00.000Z", "flight_count": 1439 }, { "dep_month": "2005-02-01T00:00:00.000Z", "flight_count": 1281 }, { "dep_month": "2005-01-01T00:00:00.000Z", "flight_count": 1421 } ], "shared_axes": [ { "dep_month": "2005-12-01T00:00:00.000Z", "flight_count": 1606 }, { "dep_month": "2005-11-01T00:00:00.000Z", "flight_count": 1448 }, { "dep_month": "2005-10-01T00:00:00.000Z", "flight_count": 1543 }, { "dep_month": "2005-09-01T00:00:00.000Z", "flight_count": 1466 }, { "dep_month": "2005-08-01T00:00:00.000Z", "flight_count": 1582 }, { "dep_month": "2005-07-01T00:00:00.000Z", "flight_count": 1564 }, { "dep_month": "2005-06-01T00:00:00.000Z", "flight_count": 1383 }, { "dep_month": "2005-05-01T00:00:00.000Z", "flight_count": 1384 }, { "dep_month": "2005-04-01T00:00:00.000Z", "flight_count": 1432 }, { "dep_month": "2005-03-01T00:00:00.000Z", "flight_count": 1439 }, { "dep_month": "2005-02-01T00:00:00.000Z", "flight_count": 1281 }, { "dep_month": "2005-01-01T00:00:00.000Z", "flight_count": 1421 } ] }, { "nickname": "USAir", "flight_count": 37683, "default_independent": [ { "dep_month": "2005-12-01T00:00:00.000Z", "flight_count": 333 }, { "dep_month": "2005-11-01T00:00:00.000Z", "flight_count": 470 }, { "dep_month": "2005-10-01T00:00:00.000Z", "flight_count": 651 }, { "dep_month": "2005-09-01T00:00:00.000Z", "flight_count": 652 }, { "dep_month": "2005-08-01T00:00:00.000Z", "flight_count": 723 }, { "dep_month": "2005-07-01T00:00:00.000Z", "flight_count": 686 }, { "dep_month": "2005-06-01T00:00:00.000Z", "flight_count": 645 }, { "dep_month": "2005-05-01T00:00:00.000Z", "flight_count": 663 }, { "dep_month": "2005-04-01T00:00:00.000Z", "flight_count": 686 }, { "dep_month": "2005-03-01T00:00:00.000Z", "flight_count": 667 }, { "dep_month": "2005-02-01T00:00:00.000Z", "flight_count": 578 }, { "dep_month": "2005-01-01T00:00:00.000Z", "flight_count": 692 } ], "shared_axes": [ { "dep_month": "2005-12-01T00:00:00.000Z", "flight_count": 333 }, { "dep_month": "2005-11-01T00:00:00.000Z", "flight_count": 470 }, { "dep_month": "2005-10-01T00:00:00.000Z", "flight_count": 651 }, { "dep_month": "2005-09-01T00:00:00.000Z", "flight_count": 652 }, { "dep_month": "2005-08-01T00:00:00.000Z", "flight_count": 723 }, { "dep_month": "2005-07-01T00:00:00.000Z", "flight_count": 686 }, { "dep_month": "2005-06-01T00:00:00.000Z", "flight_count": 645 }, { "dep_month": "2005-05-01T00:00:00.000Z", "flight_count": 663 }, { "dep_month": "2005-04-01T00:00:00.000Z", "flight_count": 686 }, { "dep_month": "2005-03-01T00:00:00.000Z", "flight_count": 667 }, { "dep_month": "2005-02-01T00:00:00.000Z", "flight_count": 578 }, { "dep_month": "2005-01-01T00:00:00.000Z", "flight_count": 692 } ] }, { "nickname": "American", "flight_count": 34577, "default_independent": [ { "dep_month": "2005-12-01T00:00:00.000Z", "flight_count": 428 }, { "dep_month": "2005-11-01T00:00:00.000Z", "flight_count": 401 }, { "dep_month": "2005-10-01T00:00:00.000Z", "flight_count": 406 }, { "dep_month": "2005-09-01T00:00:00.000Z", "flight_count": 492 }, { "dep_month": "2005-08-01T00:00:00.000Z", "flight_count": 529 }, { "dep_month": "2005-07-01T00:00:00.000Z", "flight_count": 493 }, { "dep_month": "2005-06-01T00:00:00.000Z", "flight_count": 466 }, { "dep_month": "2005-05-01T00:00:00.000Z", "flight_count": 507 }, { "dep_month": "2005-04-01T00:00:00.000Z", "flight_count": 491 }, { "dep_month": "2005-03-01T00:00:00.000Z", "flight_count": 464 }, { "dep_month": "2005-02-01T00:00:00.000Z", "flight_count": 467 }, { "dep_month": "2005-01-01T00:00:00.000Z", "flight_count": 399 } ], "shared_axes": [ { "dep_month": "2005-12-01T00:00:00.000Z", "flight_count": 428 }, { "dep_month": "2005-11-01T00:00:00.000Z", "flight_count": 401 }, { "dep_month": "2005-10-01T00:00:00.000Z", "flight_count": 406 }, { "dep_month": "2005-09-01T00:00:00.000Z", "flight_count": 492 }, { "dep_month": "2005-08-01T00:00:00.000Z", "flight_count": 529 }, { "dep_month": "2005-07-01T00:00:00.000Z", "flight_count": 493 }, { "dep_month": "2005-06-01T00:00:00.000Z", "flight_count": 466 }, { "dep_month": "2005-05-01T00:00:00.000Z", "flight_count": 507 }, { "dep_month": "2005-04-01T00:00:00.000Z", "flight_count": 491 }, { "dep_month": "2005-03-01T00:00:00.000Z", "flight_count": 464 }, { "dep_month": "2005-02-01T00:00:00.000Z", "flight_count": 467 }, { "dep_month": "2005-01-01T00:00:00.000Z", "flight_count": 399 } ] } ]
WITH __stage0 AS ( SELECT group_set, carriers_0."nickname" as "nickname__0", CASE WHEN group_set=0 THEN COUNT(1) END as "flight_count__0", CASE WHEN group_set=1 THEN DATE_TRUNC('month', base."dep_time") END as "dep_month__1", CASE WHEN group_set=1 THEN COUNT(1) END as "flight_count__1", CASE WHEN group_set=2 THEN DATE_TRUNC('month', base."dep_time") END as "dep_month__2", CASE WHEN group_set=2 THEN COUNT(1) END as "flight_count__2" FROM '../data/flights.parquet' as base LEFT JOIN '../data/carriers.parquet' AS carriers_0 ON base."carrier"=carriers_0."code" CROSS JOIN (SELECT UNNEST(GENERATE_SERIES(0,2,1)) as group_set ) as group_set GROUP BY 1,2,4,6 ) , __stage1 AS ( SELECT *, CASE WHEN GROUP_SET=0 THEN ROW_NUMBER() OVER (PARTITION BY group_set ORDER BY "flight_count__0" desc) END as __row_number__0, CASE WHEN GROUP_SET=1 THEN ROW_NUMBER() OVER (PARTITION BY CAST("nickname__0" as VARCHAR), group_set ORDER BY "dep_month__1" desc) END as __row_number__1, CASE WHEN GROUP_SET=2 THEN ROW_NUMBER() OVER (PARTITION BY CAST("nickname__0" as VARCHAR), group_set ORDER BY "dep_month__2" desc) END as __row_number__2 FROM __stage0 ) , __stage2 AS ( SELECT *, MAX(CASE WHEN group_set IN (0,1,2) THEN CASE WHEN (GROUP_SET = 0 AND __row_number__0 > 3) THEN 1 ELSE 0 END END) OVER(PARTITION BY CAST("nickname__0" as VARCHAR)) as __shaving__0 FROM __stage1 WHERE NOT ((GROUP_SET = 1 AND __row_number__1 > 12) OR (GROUP_SET = 2 AND __row_number__2 > 12)) ) , __stage3 AS ( SELECT * FROM __stage2 WHERE NOT ((group_set IN (0,1,2) AND __shaving__0 > 0) ) ) SELECT "nickname__0" as "nickname", MAX(CASE WHEN group_set=0 THEN "flight_count__0" END) as "flight_count", COALESCE(LIST({ "dep_month": "dep_month__1", "flight_count": "flight_count__1"} ORDER BY "dep_month__1" DESC NULLS LAST) FILTER (WHERE group_set=1),[]) as "default_independent", COALESCE(LIST({ "dep_month": "dep_month__2", "flight_count": "flight_count__2"} ORDER BY "dep_month__2" DESC NULLS LAST) FILTER (WHERE group_set=2),[]) as "shared_axes" FROM __stage3 GROUP BY 1 ORDER BY 2 desc NULLS LAST LIMIT 3
The same pattern works for other chart types:
## viz.bar_chart.defaults.stack ## viz.bar_chart.defaults.y.independent=true
The # viz= Shorthand
Instead of # bar_chart or # line_chart, you can use the # viz= shorthand. All chart properties work the same way:
# viz=bar { title='Flights by Carrier' subtitle='Top 10' } run: flights -> { group_by: carriers.nickname aggregate: flight_count limit: 10 }
[ { "nickname": "Southwest", "flight_count": 88751 }, { "nickname": "USAir", "flight_count": 37683 }, { "nickname": "American", "flight_count": 34577 }, { "nickname": "Northwest", "flight_count": 33580 }, { "nickname": "United", "flight_count": 32757 }, { "nickname": "Delta", "flight_count": 32130 }, { "nickname": "Continental Express", "flight_count": 16074 }, { "nickname": "American Eagle", "flight_count": 15869 }, { "nickname": "Atlantic Southeast", "flight_count": 15769 }, { "nickname": "America West", "flight_count": 9750 } ]
SELECT carriers_0."nickname" as "nickname", COUNT(1) as "flight_count" FROM '../data/flights.parquet' as base LEFT JOIN '../data/carriers.parquet' AS carriers_0 ON base."carrier"=carriers_0."code" GROUP BY 1 ORDER BY 2 desc NULLS LAST LIMIT 10
Theme Properties
Use ## theme.* at the model level to customize the appearance of rendered results. Individual views can override with # theme.*.
## theme.tableHeaderColor=darkblue source: airports is duckdb.table('../data/airports.parquet') extend { measure: airport_count is count() }
run: airports -> { group_by: state aggregate: airport_count limit: 5 }
[ { "state": "TX", "airport_count": 1845 }, { "state": "CA", "airport_count": 984 }, { "state": "IL", "airport_count": 890 }, { "state": "FL", "airport_count": 856 }, { "state": "PA", "airport_count": 804 } ]
SELECT base."state" as "state", COUNT(1) as "airport_count" FROM '../data/airports.parquet' as base GROUP BY 1 ORDER BY 2 desc NULLS LAST LIMIT 5
A view can override the model-level theme:
# theme.tableHeaderColor=darkred run: airports -> { group_by: state aggregate: airport_count limit: 5 }
[ { "state": "TX", "airport_count": 1845 }, { "state": "CA", "airport_count": 984 }, { "state": "IL", "airport_count": 890 }, { "state": "FL", "airport_count": 856 }, { "state": "PA", "airport_count": 804 } ]
SELECT base."state" as "state", COUNT(1) as "airport_count" FROM '../data/airports.parquet' as base GROUP BY 1 ORDER BY 2 desc NULLS LAST LIMIT 5
Available Theme Properties
| Property | Description | Example values |
|---|---|---|
tableBodyColor |
Text color for table body cells | blue, #333, rgb(0,0,0) |
tableHeaderColor |
Text color for table headers | gray, #666 |
tableBodyWeight |
Font weight for table body | normal, bold, 400 |
tableHeaderWeight |
Font weight for table headers | bold, 600 |
tableFontSize |
Font size for tables | 12px, 0.9em |
tableRowHeight |
Row height for tables | 24px, 2em |
tableBackground |
Background color for tables | white, #f5f5f5 |
tableBorder |
Border style for table cells | 1px solid #ccc |
tableGutterSize |
Spacing between table sections | 8px |
tablePinnedBackground |
Background for pinned columns | #fafafa |
tablePinnedBorder |
Border for pinned column edges | 2px solid #ddd |
fontFamily |
Font family for all rendered output | monospace, 'Helvetica Neue' |
background |
Overall background color | white, transparent |