Skip to content

// ABOUTME: Waffle Mark Showcase - comprehensive examples of Observable Plot waffle mark // ABOUTME: Demonstrates basic waffles, stacking, grouping, unit/gap configuration, styling, and advanced patterns

Waffle Mark Showcase

Waffle marks display discrete unit squares arranged in a grid pattern, making them ideal for showing part-to-whole relationships and proportions. Unlike bar charts that use continuous height, waffle charts use individual square units to represent quantities, making fractional amounts and percentages more intuitive.

Quick Overview

This showcase demonstrates:

  1. Basic vertical and horizontal waffles
  2. Colored and categorical waffles
  3. Stacked waffle charts for composition
  4. Grouped waffles for comparison
  5. Custom unit sizes and gaps
  6. Styling and customization options
  7. Advanced patterns and multi-mark compositions

Basic Waffle Charts

Simple Vertical Waffle (waffleY)

A basic waffle chart showing counts as grid units stacked vertically.

View Source
data:
  source: [
    {"category": "apples", "value": 212},
    {"category": "bananas", "value": 207},
    {"category": "oranges", "value": 315},
    {"category": "pears", "value": 160}
  ]
engine: plot
title: Basic Vertical Waffle Chart
width: 800
height: 450
marks:
  - type: waffleY
    configuration:
      x: category
      y: value
      fill: category
x:
  label: Fruit Type
y:
  label: Count
color:
  legend: true
grid: true
spacingLeft: 50
spacingRight: 50

Simple Horizontal Waffle (waffleX)

The same data displayed horizontally with waffleX for alternative layout.

View Source
data:
  source: [
    {"category": "apples", "value": 212},
    {"category": "bananas", "value": 207},
    {"category": "oranges", "value": 315},
    {"category": "pears", "value": 160}
  ]
engine: plot
title: Basic Horizontal Waffle Chart
width: 600
height: 450
marks:
  - type: waffleX
    configuration:
      y: category
      x: value
      fill: category
x:
  label: Count
y:
  label: Fruit Type
color:
  legend: true
grid: true
spacingLeft: 50
spacingRight: 50

Categorical Waffle with Explicit Colors

Waffle chart with predefined color mapping for categories.

View Source
data:
  source: [
    {"fruit": "apples", "count": 180},
    {"fruit": "bananas", "count": 240},
    {"fruit": "oranges", "count": 290},
    {"fruit": "grapes", "count": 150},
    {"fruit": "strawberries", "count": 120}
  ]
engine: plot
title: Colored Categorical Waffle
width: 600
height: 450
marks:
  - type: waffleY
    configuration:
      x: fruit
      y: count
      fill: fruit
x:
  label: Fruit Type
y:
  label: Quantity
color:
  scheme: category10
  legend: true
grid: true
spacingLeft: 50
spacingRight: 50

Stacked and Grouped Waffles

Stacked Waffle Chart

Multiple categories stacked within each group to show composition.

View Source
data:
  source: [
    {"region": "North", "product": "A", "sales": 45},
    {"region": "North", "product": "B", "sales": 32},
    {"region": "North", "product": "C", "sales": 28},
    {"region": "South", "product": "A", "sales": 52},
    {"region": "South", "product": "B", "sales": 38},
    {"region": "South", "product": "C", "sales": 35},
    {"region": "East", "product": "A", "sales": 48},
    {"region": "East", "product": "B", "sales": 41},
    {"region": "East", "product": "C", "sales": 30},
    {"region": "West", "product": "A", "sales": 55},
    {"region": "West", "product": "B", "sales": 39},
    {"region": "West", "product": "C", "sales": 33}
  ]
engine: plot
title: Stacked Waffle Chart - Product Mix by Region
width: 600
height: 450
marks:
  - type: waffleY
    configuration:
      x: region
      y: sales
      fill: product
x:
  label: Region
y:
  label: Total Sales
color:
  legend: true
grid: true

Normalized Stacked Waffle (100%)

Stacked waffles scaled to 100 units per group for percentage comparison.

View Source
data:
  source: [
    {"quarter": "Q1", "channel": "Online", "revenue": 340},
    {"quarter": "Q1", "channel": "Retail", "revenue": 180},
    {"quarter": "Q1", "channel": "Wholesale", "revenue": 80},
    {"quarter": "Q2", "channel": "Online", "revenue": 380},
    {"quarter": "Q2", "channel": "Retail", "revenue": 160},
    {"quarter": "Q2", "channel": "Wholesale", "revenue": 60},
    {"quarter": "Q3", "channel": "Online", "revenue": 420},
    {"quarter": "Q3", "channel": "Retail", "revenue": 140},
    {"quarter": "Q3", "channel": "Wholesale", "revenue": 40},
    {"quarter": "Q4", "channel": "Online", "revenue": 500},
    {"quarter": "Q4", "channel": "Retail", "revenue": 120},
    {"quarter": "Q4", "channel": "Wholesale", "revenue": 30}
  ]
engine: plot
title: Normalized Stacked Waffle - Revenue Distribution Trend
width: 600
height: 450
marks:
  - type: waffleY
    configuration:
      x: quarter
      y: revenue
      fill: channel
      stack: true
      normalize: true
x:
  label: Quarter
y:
  label: Percentage (normalized to 100)
color:
  legend: true
grid: true
margin:
	left: 50
	right: 50

Side-by-Side Grouped Waffles

Multiple waffles grouped together for direct comparison.

View Source
data:
  source: [
    {"year": "2022", "department": "Sales", "headcount": 45},
    {"year": "2022", "department": "Engineering", "headcount": 78},
    {"year": "2022", "department": "Marketing", "headcount": 28},
    {"year": "2022", "department": "Support", "headcount": 32},
    {"year": "2023", "department": "Sales", "headcount": 52},
    {"year": "2023", "department": "Engineering", "headcount": 95},
    {"year": "2023", "department": "Marketing", "headcount": 35},
    {"year": "2023", "department": "Support", "headcount": 40},
    {"year": "2024", "department": "Sales", "headcount": 58},
    {"year": "2024", "department": "Engineering", "headcount": 112},
    {"year": "2024", "department": "Marketing", "headcount": 42},
    {"year": "2024", "department": "Support", "headcount": 48}
  ]
engine: plot
title: Grouped Waffle - Department Headcount by Year
width: 600
height: 450
marks:
  - type: waffleY
    configuration:
      x: department
      y: headcount
      fill: year
x:
  label: Department
y:
  label: Headcount
color:
  legend: true
grid: true
spacingLeft: 50
spacingRight: 50

Unit Size and Gap Configuration

Default Unit Size

Waffle chart with default unit dimensions and standard gap spacing.

View Source
data:
  source: [
    {"category": "A", "value": 120},
    {"category": "B", "value": 95},
    {"category": "C", "value": 140},
    {"category": "D", "value": 85},
    {"category": "E", "value": 110}
  ]
engine: plot
title: Default Unit Size Waffle
width: 600
height: 450
marks:
  - type: waffleY
    configuration:
      x: category
      y: value
      fill: category
x:
  label: Category
y:
  label: Value
color:
  legend: true
grid: true
spacingLeft: 50
spacingRight: 50

Large Unit Size

Increased unit size creates fewer but larger squares, improving readability for smaller datasets.

View Source
data:
  source: [
    {"category": "A", "value": 24},
    {"category": "B", "value": 19},
    {"category": "C", "value": 28},
    {"category": "D", "value": 17},
    {"category": "E", "value": 22}
  ]
engine: plot
title: "Large Unit Size Waffle (unit: 5)"
width: 600
height: 450
marks:
  - type: waffleY
    configuration:
      x: category
      y: value
      fill: category
      unit: 5
x:
  label: Category
y:
  label: Value (5 units per square)
color:
  legend: true
grid: true
spacingLeft: 50
spacingRight: 50

Custom Gap Spacing

Adjusted gap between units to control visual density.

View Source
data:
  source: [
    {"category": "A", "value": 120},
    {"category": "B", "value": 95},
    {"category": "C", "value": 140},
    {"category": "D", "value": 85},
    {"category": "E", "value": 110}
  ]
engine: plot
title: "Waffle with Large Gap (gap: 8)"
width: 600
height: 450
marks:
  - type: waffleY
    configuration:
      x: category
      y: value
      fill: category
      gap: 8
x:
  label: Category
y:
  label: Value
color:
  legend: true
grid: true
spacingLeft: 50
spacingRight: 50

Combined Unit and Gap Configuration

Large units with increased gap for maximum clarity and visual separation.

View Source
data:
  source: [
    {"category": "A", "value": 30},
    {"category": "B", "value": 25},
    {"category": "C", "value": 35},
    {"category": "D", "value": 20},
    {"category": "E", "value": 28}
  ]

engine: plot
title: "Large Units + Large Gap (unit: 4, gap: 6)"
width: 600
height: 450
marks:
  - type: waffleY
    configuration:
      x: category
      y: value
      fill: category
      unit: 4
      gap: 6
x:
  label: Category
y:
  label: Value (4 units per square)
color:
  legend: true
grid: true
spacingLeft: 50
spacingRight: 50

Styling and Customization

Sequential Color Scheme

Waffles with sequential color encoding to show value intensity.

View Source
data:
  source: [
    {"item": "Item1", "score": 15},
    {"item": "Item2", "score": 28},
    {"item": "Item3", "score": 42},
    {"item": "Item4", "score": 35},
    {"item": "Item5", "score": 48},
    {"item": "Item6", "score": 22},
    {"item": "Item7", "score": 38},
    {"item": "Item8", "score": 32}
  ]

engine: plot
title: Waffle with Sequential Color (Blues scheme)
width: 600
height: 450
marks:
  - type: waffleY
    configuration:
      x: item
      y: score
      fill: score
x:
  label: Item
y:
  label: Score
color:
  scheme: Blues
  legend: true
grid: true
spacingLeft: 50
spacingRight: 50

Custom Fill and Stroke Styling

Waffle with custom stroke color and fill opacity.

View Source
data:
  source: [
    {"type": "Excellent", "count": 180},
    {"type": "Good", "count": 240},
    {"type": "Fair", "count": 120},
    {"type": "Poor", "count": 60}
  ]

engine: plot
title: Waffle with Stroke and Opacity
width: 600
height: 450
marks:
  - type: waffleY
    configuration:
      x: type
      y: count
      fill: type
      stroke: "#333"
      strokeWidth: 0.5
      fillOpacity: 0.8
x:
  label: Rating Type
y:
  label: Count
color:
  legend: true
grid: true
spacingLeft: 50
spacingRight: 50

Diverging Color Scheme

Waffles using diverging colors to emphasize contrast between categories.

View Source
data:
  source: [
    {"sentiment": "Very Negative", "responses": 35},
    {"sentiment": "Negative", "responses": 85},
    {"sentiment": "Neutral", "responses": 120},
    {"sentiment": "Positive", "responses": 180},
    {"sentiment": "Very Positive", "responses": 140}
  ]

engine: plot
title: Waffle with Diverging Colors - Sentiment Distribution
width: 600
height: 450
marks:
  - type: waffleY
    configuration:
      x: sentiment
      y: responses
      fill: sentiment
x:
  label: Sentiment
y:
  label: Number of Responses
color:
  scheme: RdYlGn
  legend: true
grid: true
spacingLeft: 50
spacingRight: 50

Advanced Patterns

Horizontal Stacked Waffle

Horizontal layout with stacked composition for space-efficient display.

View Source
data:
  source: [
    {"status": "Completed", "project": "ProjectA", "tasks": 45},
    {"status": "In Progress", "project": "ProjectA", "tasks": 28},
    {"status": "Blocked", "project": "ProjectA", "tasks": 12},
    {"status": "Completed", "project": "ProjectB", "tasks": 52},
    {"status": "In Progress", "project": "ProjectB", "tasks": 32},
    {"status": "Blocked", "project": "ProjectB", "tasks": 8},
    {"status": "Completed", "project": "ProjectC", "tasks": 38},
    {"status": "In Progress", "project": "ProjectC", "tasks": 42},
    {"status": "Blocked", "project": "ProjectC", "tasks": 15}
  ]

engine: plot
title: Horizontal Stacked Waffle - Project Status Distribution
width: 600
height: 450
marks:
  - type: waffleX
    configuration:
      y: project
      x: tasks
      fill: status
y:
  label: Project
x:
  label: Task Count
color:
  legend: true
grid: true
spacingLeft: 50
spacingRight: 50

Waffle with Multiple Marks

Combining waffles with other marks (dots, rules) for enriched visualization.

View Source
data:
  source: [
    {"week": "Week1", "actual": 180, "target": 200},
    {"week": "Week2", "actual": 220, "target": 200},
    {"week": "Week3", "actual": 195, "target": 200},
    {"week": "Week4", "actual": 240, "target": 200},
    {"week": "Week5", "actual": 210, "target": 200},
    {"week": "Week6", "actual": 230, "target": 200},
    {"week": "Week7", "actual": 250, "target": 200},
    {"week": "Week8", "actual": 215, "target": 200}
  ]
engine: plot
title: Waffle with Target Reference Line
width: 600
height: 450
marks:
  - type: waffleY
    configuration:
      x: week
      y: actual
      fill: "#3498db"
  - type: ruleY
    configuration:
      y: 200
      stroke: "#e74c3c"
      strokeWidth: 1
      strokeDasharray: "4,4"
x:
  label: Week
y:
  label: "Units (target: 200)"
grid: true
spacingLeft: 50
spacingRight: 50

Grouped Horizontal Waffles

Multiple horizontal waffles side-by-side for comparative analysis.

View Source
data:
  source: [
    {"browser": "Chrome", "year": "2022", "users": 280},
    {"browser": "Firefox", "year": "2022", "users": 150},
    {"browser": "Safari", "year": "2022", "users": 120},
    {"browser": "Edge", "year": "2022", "users": 90},
    {"browser": "Chrome", "year": "2023", "users": 350},
    {"browser": "Firefox", "year": "2023", "users": 140},
    {"browser": "Safari", "year": "2023", "users": 135},
    {"browser": "Edge", "year": "2023", "users": 110},
    {"browser": "Chrome", "year": "2024", "users": 420},
    {"browser": "Firefox", "year": "2024", "users": 130},
    {"browser": "Safari", "year": "2024", "users": 155},
    {"browser": "Edge", "year": "2024", "users": 145}
  ]
engine: plot
title: Browser Market Share Waffle Charts
width: 600
height: 500
marks:
  - type: waffleX
    configuration:
      y: browser
      x: users
      fill: year
x:
  label: Number of Users (thousands)
y:
  label: Browser
color:
  legend: true
grid: true
spacingLeft: 50
spacingRight: 50

Multi-Category Comparison Waffle

Waffles comparing multiple categories with size-coded values.

View Source
data:
  source: [
    {"quarter": "Q1", "tier": "Premium", "units": 85},
    {"quarter": "Q1", "tier": "Standard", "units": 145},
    {"quarter": "Q1", "tier": "Basic", "units": 70},
    {"quarter": "Q2", "tier": "Premium", "units": 95},
    {"quarter": "Q2", "tier": "Standard", "units": 160},
    {"quarter": "Q2", "tier": "Basic", "units": 65},
    {"quarter": "Q3", "tier": "Premium", "units": 110},
    {"quarter": "Q3", "tier": "Standard", "units": 175},
    {"quarter": "Q3", "tier": "Basic", "units": 55},
    {"quarter": "Q4", "tier": "Premium", "units": 130},
    {"quarter": "Q4", "tier": "Standard", "units": 190},
    {"quarter": "Q4", "tier": "Basic", "units": 50}
  ]
engine: plot
title: Subscription Tier Distribution by Quarter
width: 600
height: 450
marks:
  - type: waffleY
    configuration:
      x: quarter
      y: units
      fill: tier
      stack: true
x:
  label: Quarter
y:
  label: Units Sold
color:
  legend: true
grid: true
spacingLeft: 50
spacingRight: 50

Mini Waffle Charts (Small Units)

Compact waffles using small units for space-efficient data presentation.

View Source
data:
  source: [
    {"metric": "Accuracy", "value": 950},
    {"metric": "Precision", "value": 920},
    {"metric": "Recall", "value": 890},
    {"metric": "F1-Score", "value": 915},
    {"metric": "AUC-ROC", "value": 945}
  ]
engine: plot
title: "Model Performance Metrics (unit: 10)"
width: 600
height: 400
marks:
  - type: waffleY
    configuration:
      x: metric
      y: value
      fill: metric
      unit: 10
x:
  label: Metric
y:
  label: Score (per 10 units)
color:
  legend: true
grid: true
spacingLeft: 50
spacingRight: 50

Usage Notes

Waffle Mark Characteristics

  • Part-to-whole representation: Each square represents a discrete unit, making proportions and fractions intuitive
  • Categorical layout: X-axis (waffleY) or Y-axis (waffleX) typically shows categories
  • Quantitative encoding: The count or value maps to number of unit squares
  • Stacking support: Multiple series can be stacked for composition analysis
  • Performance: SVG pattern-based rendering optimizes performance for large datasets

Configuration Options

  • unit: Size of each unit (default: 1). Higher values create fewer but larger squares
  • gap: Space between units (default: 1 pixel). Adjust to control visual density
  • fill: Color encoding channel (category, value, or solid color)
  • stroke: Outline color for units
  • fillOpacity: Transparency of unit squares (0-1)

Best Practices

  1. Use for proportions: Waffles excel at showing part-to-whole relationships and percentages
  2. Limit categories: Too many categories make waffles hard to interpret; 3-8 categories work best
  3. Unit sizing: Larger units improve readability but show less detail; balance based on data granularity
  4. Stacking vs grouping: Stack for composition analysis, group side-by-side for comparison
  5. Color schemes: Use categorical schemes for distinct categories, sequential for ordered values

When to Use Waffles

  • Survey responses and Likert scale data
  • Task completion and project status tracking
  • Market share and portfolio composition
  • Goal progress visualization (100-unit squares for percentages)
  • Risk/severity matrices with discrete categories

Comprehensive showcase of Observable Plot waffle marks for DataGlass plugin

Released under the MIT License. Built by Boundary Lab.