---
title: Build waffle charts with Kibana
description: Instructions and best practices for building waffle charts with Kibana Lens in Elastic.
url: https://docs-v3-preview.elastic.dev/elastic/docs-content/pull/5399/explore-analyze/visualize/charts/waffle-charts
products:
  - Kibana
applies_to:
  - Elastic Cloud Serverless: Generally available
  - Elastic Stack: Generally available
---

# Build waffle charts with Kibana
Waffle charts display data as a 10x10 grid of small squares, where each square represents 1% of the whole. They are ideal for showing percentages, visualizing survey results, and making proportions intuitive by representing data as discrete units. They work best with fewer than 10 categories.
Like [pie charts](https://docs-v3-preview.elastic.dev/elastic/docs-content/pull/5399/explore-analyze/visualize/charts/pie-charts), waffle charts show part-to-whole relationships. However, waffle charts make it easier to compare similarly-sized proportions (for example, 23% vs. 27%) because areas in a grid are easier to distinguish than angles in a circle. Choose a pie chart when you have a small number of slices (2-4) with clearly different sizes, or when you want to use a donut layout.
You can create waffle charts in Kibana using [**Lens**](https://docs-v3-preview.elastic.dev/elastic/docs-content/pull/5399/explore-analyze/visualize/lens).
![Example Lens waffle charts showing response status breakdown and OS distribution](https://docs-v3-preview.elastic.dev/elastic/docs-content/pull/5399/explore-analyze/images/waffle-chart-example.png)

## Build a waffle chart

Before you start, make sure you have data [indexed into Elasticsearch](https://docs-v3-preview.elastic.dev/elastic/docs-content/pull/5399/manage-data/ingest) or [install sample data](https://docs-v3-preview.elastic.dev/elastic/docs-content/pull/5399/manage-data/ingest/sample-data). By default, Lens uses [data views](https://docs-v3-preview.elastic.dev/elastic/docs-content/pull/5399/explore-analyze/find-and-organize/data-views) to access your Elasticsearch data. Data views are created automatically in most cases when you ingest data. You can also [create one manually](https://docs-v3-preview.elastic.dev/elastic/docs-content/pull/5399/explore-analyze/find-and-organize/data-views) to select just the data that you want. Alternatively, you can use the [ES|QL query mode](https://docs-v3-preview.elastic.dev/elastic/docs-content/pull/5399/explore-analyze/visualize/esorql) to query your Elasticsearch data directly.
To build a waffle chart:
<stepper>
  <step title="Access Lens">
    **Lens** is Kibana's main visualization editor. You can access it:
    - From a dashboard: On the **Dashboards** page, open or create the dashboard where you want to add a waffle chart, then add a new visualization.
    - From the **Visualize library** page by creating a new visualization.
  </step>

  <step title="Set the visualization to Waffle">
    New visualizations often start as **Bar** charts.Using the **Visualization type** dropdown, select **Waffle**.
  </step>

  <step title="Define the data to show">
    1. Select the data view that contains your data.
    2. Configure the [**Group by**](#group-by-settings) dimension to define the categories. Each category is displayed as a colored section of the waffle.
    3. Configure the [**Metric**](#metric-settings) dimension to define the value for each category. This determines how many squares each category occupies.
    Optionally:
    - Enable [**Multiple metrics**](#percentage-completion) in the layer settings to define each category as a separate metric.
    The chart preview updates to show a grid of colored squares. Each color represents a category, and the number of squares reflects its proportion of the total.
  </step>

  <step title="Customize the chart to follow best practices">
    Tweak the appearance of the chart to your needs. Consider the following best practices:
    <definitions>
      <definition term="Limit categories">
        Keep your waffle chart to a maximum of 6-8 categories. More categories make the chart difficult to read.
      </definition>
      <definition term="Use intuitive colors">
        Assign colors that have semantic meaning when possible (for example, green for success, red for errors). Use the [color mapping feature](/elastic/docs-content/pull/5399/explore-analyze/visualize/lens#assign-colors-to-terms) for consistent coloring.
      </definition>
      <definition term="Order categories meaningfully">
        Arrange categories from largest to smallest or in a natural order (such as satisfaction ratings from low to high).
      </definition>
    </definitions>
    Refer to [Waffle chart settings](#waffle-chart-settings) to find all configuration options for your waffle chart.
  </step>

  <step title="Save the chart">
    - If you accessed Lens from a dashboard, select **Save and return** to save the visualization and add it to that dashboard, or select **Save to library** to add the visualization to the Visualize library and reuse it later.
    - If you accessed Lens from the Visualize library, select **Save**. A menu opens and lets you add the visualization to a dashboard and to the Visualize library.
  </step>
</stepper>


## Advanced waffle chart scenarios


### Show percentage completion with multiple metrics

You can use **Multiple metrics** to show progress toward a goal, with filled squares for completed work and empty squares for remaining work.

#### Example: Revenue progress toward a sales target

This example uses the **Kibana Sample Data eCommerce** data set. If you haven't installed it yet, refer to [Sample data](https://docs-v3-preview.elastic.dev/elastic/docs-content/pull/5399/manage-data/ingest/sample-data) for instructions.
1. Create a **Waffle** chart using the **Kibana Sample Data eCommerce** data view.
2. Open **Layer settings**:
   - <applies-to>Elastic Cloud Serverless: Generally available</applies-to> <applies-to>Elastic Stack: Generally available since 9.3</applies-to> Select `app_management` **Layer settings**.
- <applies-to>Elastic Stack: Generally available from 9.0 to 9.2</applies-to> Select `boxes_horizontal`, then select **Layer settings**.
3. Select **Multiple metrics**, then close the layer settings.
4. Add two metrics:
   - **Revenue earned**: Set to `Sum` of `taxful_total_price`. Name it "Revenue earned" and assign a green color.
- **Remaining to goal**: Set to a [formula](/elastic/docs-content/pull/5399/explore-analyze/visualize/lens#lens-formulas): `500000 - sum(taxful_total_price)`. Name it "Remaining to goal" and assign a gray color.
5. The chart shows how close revenue is to the $500,000 target. Each green square represents 1% of the goal achieved.

![Waffle chart showing revenue progress toward a sales target](https://docs-v3-preview.elastic.dev/elastic/docs-content/pull/5399/explore-analyze/images/waffle-scenario-completion.png)

## Waffle chart settings

Customize your waffle chart to display exactly the information you need, formatted the way you want.

### Group by settings

The **Group by** dimension defines how the waffle is divided into colored sections. Waffle charts support a single **Group by** dimension.
<definitions>
  <definition term="Data">
    The **Group by** dimension supports the following functions:
    - **Top values**: Create sections for the most common values in a field.
      - **Field**: Select the field to group by. You can add up to 4 fields to create multi-term sections. When multiple fields are selected, each section represents a unique combination of values across those fields. You can reorder the fields by dragging them to change their priority.
    - **Number of values**: How many top values to display.
      - **Rank by**: Specifies the dimension the top values are ranked by. Available options:
      - **Count of records**: Rank by the number of documents containing each value. This is the default when a metric is defined.
      - **Alphabetical**: Rank by the term key alphabetically. This is the default when no metric is defined.
      - **Rarity**: Find terms that appear in very few documents, using a [rare terms aggregation](https://docs-v3-preview.elastic.dev/elastic/elasticsearch/tree/main/reference/aggregations/search-aggregations-bucket-rare-terms-aggregation). You can configure the **Max doc count** to set the maximum number of documents a term can appear in to be considered rare (default: 1, max: 100). Only available for non-numeric fields and single-field terms.
      - **Significance**: Find statistically unusual terms compared to the overall data set, using a [significant terms aggregation](https://docs-v3-preview.elastic.dev/elastic/elasticsearch/tree/main/reference/aggregations/search-aggregations-bucket-significantterms-aggregation). Only available for `keyword` fields and single-field terms.
      - **Custom**: Define a custom metric aggregation to rank by (for example, rank by the sum of a numeric field rather than by count).
      - **Rank direction**: Ascending or descending order. Disabled when **Rank by** is set to **Rarity** or **Significance**.
      - **Collapse by**: Aggregate values into a single number using `Sum`, `Average`, `Min`, or `Max`.
      <dropdown title="Advanced settings">
      Several advanced options allow you to refine the behavior of the breakdown:
      - **Include documents without the selected field**: Off by default.
      - **Group remaining values as "Other"**: On by default.
      - **Enable accuracy mode**: This option improves results for high-cardinality data, but increases the load on the Elasticsearch cluster.
      - **Include values**: Values from the breakdown dimension to always show a tile for.
      - **Exclude values**: Values from the breakdown dimension to always exclude from the displayed tiles.
      </dropdown>
    - **Date histogram**: Group data into time-based buckets.
      - **Field**: Select the date field to use for the time-based grouping.
      - **Include empty rows**: This option is on by default. Turn it off to exclude empty rows from the data.
      - **Bind to global time picker**: Associate the selected field to the Lens or dashboard main time selector.
      - **Minimum interval**: Define the time interval for aggregating the data. For example, `30s`, `20m`, `24h`, `2d`, `1w`, `1M`
      - **Drop partial intervals**: Exclude incomplete intervals from the data. This option is off by default.
      - **Collapse by**: Aggregate values into a single number using `Sum`, `Average`, `Min`, or `Max`.
    - **Intervals**: Create numeric ranges for continuous data.
      - **Field**: Select the numeric field to create intervals from.
    - **Include empty rows**: Include intervals with no matching documents.
    - **Collapse by**: Aggregate values into a single number using `Sum`, `Average`, `Min`, or `Max`.
    - **Filters**: Define custom KQL filters to create specific sections.
      - **Collapse by**: Aggregate values into a single number using `Sum`, `Average`, `Min`, or `Max`.
  </definition>
  <definition term="Appearance">
    - **Name**: Customize the legend label.
    - **Color mapping**: Select a color palette or assign specific colors to categories. Refer to [Assign colors to terms](/elastic/docs-content/pull/5399/explore-analyze/visualize/lens#assign-colors-to-terms) for details.
  </definition>
</definitions>


### Metric settings

The **Metric** dimension defines the value for each category, determining how many squares each section occupies.
<definitions>
  <definition term="Data">
    The value that determines how many squares each category fills. When you drag a field onto the chart, Kibana suggests a function based on the field type. You can use aggregation functions like `Sum`, `Average`, `Count`, `Median`, and more, or create custom calculations with [formulas](/elastic/docs-content/pull/5399/explore-analyze/visualize/lens#lens-formulas).
    <dropdown title="Advanced settings">
      Depending on the data you defined, several options allow you to apply additional filtering to the data taken into account to compute the final value to show.Based on the type of visualization you're creating, only some of the following options can be available:
      - **Normalize by unit**: Normalize the metric values to show per unit of time.
      - **Filter by**: Specify a query.
      - **Reduced time range**: Reduce the time range specified on the dashboard's time filter by the specified duration.
      - **Time shift**: Shift the time range by the specified duration. This is useful if the value should use a different time range than the one selected on the dashboard.
      - **Hide zero values**: Don't show values equal to zero. This option is on by default.
    </dropdown>
  </definition>
  <definition term="Appearance">
    - **Name**: Customize the metric label displayed in tooltips and legends.
    - **Value format**: Control how numeric values are displayed (number, percent, bytes, and more).
    - **Series color**: When using multiple metrics without a **Group by** dimension, assign a specific color to each metric.
  </definition>
</definitions>


### General layout

When creating or editing a visualization, you can customize the legend from the ![Legend icon](https://docs-v3-preview.elastic.dev/elastic/docs-content/pull/5399/explore-analyze/images/kibana-legend-icon.svg) **Legend** menu.
<note>
  Waffle charts do not have configurable style settings. The chart automatically displays labels and percentages on each section.
</note>


#### Legend settings

<definitions>
  <definition term="Visibility">
    Specify whether to automatically show the legend or hide it:
    - **Auto**: Show the legend when there are multiple categories.
    - **Show**: Always show the legend (default).
    - **Hide**: Never show the legend.
  </definition>
  <definition term="Width">
    Control the width of the legend panel: **Small**, **Medium** (default), **Large**, or **Extra large**.
  </definition>
  <definition term="Show value">
    Toggle whether to display the numeric value alongside each legend entry. This is enabled by default.
  </definition>
  <definition term="Label truncation">
    Toggle whether to truncate long legend labels. When enabled, set the **Line limit** to control how many lines to display before truncating (1-5, default: 1).
  </definition>
</definitions>


## Waffle chart examples

The following examples show various configuration options for building impactful waffle charts.
<definitions>
  <definition term="Response status breakdown">
    Visualize the proportion of successful and failed HTTP requests at a glance:
    - Example based on: Kibana Sample Data Logs
    - **Group by**: Filters
      - "Success (2xx/3xx)": `response.keyword >= "200" AND response.keyword < "400"`
    - "Client errors (4xx)": `response.keyword >= "400" AND response.keyword < "500"`
    - "Server errors (5xx)": `response.keyword >= "500"`
    - **Metric**: Count
    - **Color mapping**: Green for success, yellow for client errors, red for server errors
  </definition>
</definitions>

![Waffle chart showing response status breakdown](https://docs-v3-preview.elastic.dev/elastic/docs-content/pull/5399/explore-analyze/images/waffle-example-response-status.png)
<definitions>
  <definition term="OS distribution">
    Show the distribution of operating systems used by your website visitors:
    - Example based on: Kibana Sample Data Logs
    - **Group by**: `machine.os.keyword` (Top 5 values)
    - **Metric**: Count
  </definition>
</definitions>

![Waffle chart showing OS distribution](https://docs-v3-preview.elastic.dev/elastic/docs-content/pull/5399/explore-analyze/images/waffle-example-os.png)