Colour and in-cell visuals

Conditional formatting

Add conditional formatting when a table needs to surface outliers or rank itself, like flagging a whole row under quota or bolding the top performers, without a separate chart.

What you can do

  • conditionalFormat is an array of up to 100 rules, each pairing a where predicate with an apply style; stopIfMatched (default false) stops evaluating later rules on a cell once one already matched it.
  • where.op is one of 14 operators: eq, neq, gt, gte, lt, lte, between, in, notIn, contains, isNull, isNotNull, topN, and bottomN.
  • apply sets fill, textColor, weight (normal, medium, bold), italic, underline, strikethrough, and align.
  • target defaults to cell; set it to row to style the whole row instead, or to another column’s field to style that column only when this rule matches.
  • Rules can live on TableSpec.conditionalFormat (panel-level, evaluated first, up to 100) or on a TableColumn.conditionalFormat (up to 50 per column, evaluated after).
  • A topN or bottomN rule ranks the whole column rather than testing one cell in isolation.

Applies only to a table panel, at the panel level (TableSpec.conditionalFormat) or per column (TableColumn.conditionalFormat); no chart:* panel has an equivalent.

Spec

View spec
{
  "id": "rep-attainment-table",
  "type": "table",
  "title": "Rep attainment",
  "data": {
    "rows": [
      {
        "rep": "A. Chen",
        "region": "West",
        "attainment": 62,
        "revenue": 410000
      },
      {
        "rep": "B. Ortiz",
        "region": "East",
        "attainment": 88,
        "revenue": 530000
      },
      {
        "rep": "C. Singh",
        "region": "West",
        "attainment": 95,
        "revenue": 610000
      },
      {
        "rep": "D. Wallace",
        "region": "East",
        "attainment": 73,
        "revenue": 295000
      }
    ]
  },
  "spec": {
    "columns": [
      {
        "field": "rep",
        "label": "Rep"
      },
      {
        "field": "region"
      },
      {
        "field": "attainment",
        "label": "Attainment",
        "format": {
          "type": "percentage"
        },
        "align": "right"
      },
      {
        "field": "revenue",
        "format": {
          "type": "currency",
          "currency": "USD",
          "compact": true
        },
        "align": "right"
      }
    ],
    "conditionalFormat": [
      {
        "where": {
          "field": "attainment",
          "op": "lt",
          "value": 70
        },
        "apply": {
          "fill": "{semantic.negative}",
          "textColor": "white"
        },
        "target": "row",
        "stopIfMatched": true
      },
      {
        "where": {
          "field": "revenue",
          "op": "topN",
          "value": 2
        },
        "apply": {
          "weight": "bold"
        }
      }
    ]
  }
}

The first rule targets "row" and sets stopIfMatched, so a rep under 70% attainment gets a fully red row and skips the second rule; the second rule ranks revenue with topN to bold the top two rows regardless of attainment.

Try it live

Open the rich-tables template in the Builder

Open the rich-tables template, page p1-presentation, panel p1-reps for panel- and column-level conditionalFormat together, including a topN rule with stopIfMatched.

Build it in dvt

Every table capability on this site is a few lines of the same declarative JSON spec. Read the full spec format, or connect an AI agent to your warehouse and build one live in the quickstart.

Follow the build

dvt is in founding research. Leave your email and we'll reach out when there's something to see — no newsletters, no noise.

No spam. We use this to reach out directly, nothing else.