Rules / Report Design

Ensure charts use theme colours

warning ENSURE_THEME_COLOURS · ported · report layer · scope: Visual

What it checks

Visuals other than text boxes with a colour property set to a hex value instead of a theme colour, including a hex value inside a conditional formatting rule or a gradient.

Each finding names the visual, as "Sales by category" on "Overview" when it has a title and clusteredBarChart (99a57e) on "Overview" when it has none, and its detail counts the hex values, as 2 colours set to a hex value instead of a theme colour. The line is the first of them.

Example

The bars are set to a colour typed in by hand.

Fires the rule in visual.json
{
  "$schema": "https://developer.microsoft.com/json-schemas/fabric/item/report/definition/visualContainer/2.8.0/schema.json",
  "name": "99a57e01807b781d6d23",
  "position": { "x": 55, "y": 518, "z": 11006, "height": 190, "width": 505, "tabOrder": 11006 },
  "visual": {
    "visualType": "clusteredBarChart",
    "query": {
      "queryState": {
        "Category": {
          "projections": [
            {
              "field": { "Column": { "Expression": { "SourceRef": { "Entity": "Product" } }, "Property": "Category" } },
              "queryRef": "Product.Category",
              "active": true
            }
          ]
        },
        "Y": {
          "projections": [
            {
              "field": { "Measure": { "Expression": { "SourceRef": { "Entity": "Sales" } }, "Property": "Total Sales" } },
              "queryRef": "Sales.Total Sales"
            }
          ]
        }
      }
    },
    "objects": {
      "dataPoint": [
        {
          "properties": {
            "fill": { "solid": { "color": { "expr": { "Literal": { "Value": "'#1F4E79'" } } } } }
          }
        }
      ]
    }
  }
}
After the fix in visual.json
{
  "$schema": "https://developer.microsoft.com/json-schemas/fabric/item/report/definition/visualContainer/2.8.0/schema.json",
  "name": "99a57e01807b781d6d23",
  "position": { "x": 55, "y": 518, "z": 11006, "height": 190, "width": 505, "tabOrder": 11006 },
  "visual": {
    "visualType": "clusteredBarChart",
    "query": {
      "queryState": {
        "Category": {
          "projections": [
            {
              "field": { "Column": { "Expression": { "SourceRef": { "Entity": "Product" } }, "Property": "Category" } },
              "queryRef": "Product.Category",
              "active": true
            }
          ]
        },
        "Y": {
          "projections": [
            {
              "field": { "Measure": { "Expression": { "SourceRef": { "Entity": "Sales" } }, "Property": "Total Sales" } },
              "queryRef": "Sales.Total Sales"
            }
          ]
        }
      }
    },
    "objects": {
      "dataPoint": [
        {
          "properties": {
            "fill": { "solid": { "color": { "expr": { "ThemeDataColor": { "ColorId": 1, "Percent": 0 } } } } }
          }
        }
      ]
    }
  }
}

Why it matters

A colour picked from the theme is stored as a position in the theme's palette, so when the report's theme changes, for a rebrand, a dark variant, or an organizational theme, the visual changes with it. A colour typed in or picked under More colors is stored as a fixed hex value and stays where it is. After a theme change the report shows some visuals in the new palette and some in the old, and every hand-set colour has to be found and changed one visual at a time. A palette chosen for contrast, or for readers with colour vision deficiency, also protects only the visuals that use it.

How to fix it

In Power BI Desktop, select the visual, open the Format pane, find the colour (for this chart's bars, Bars, then Color), and pick a swatch from Theme colors at the top of the colour picker instead of More colors. To return a whole section of the Format pane to the theme, use Reset to default at the bottom of that section. If the report needs a colour its theme does not have, add it to the theme (View, then Themes, then Customize current theme) so that every visual can pick it from the palette. In visual.json, a theme colour is written as ThemeDataColor, with a ColorId for the swatch and a Percent for its shade, in place of the Literal hex value, as in the example.

When to ignore it

A colour that must not change with the theme is set by hand on purpose: a partner's brand colour on their own logo card, say, or party colours on an election map. Before ignoring the finding on those visuals, consider whether the colour belongs in the theme instead, where every visual can use it and a later rebrand can still reach it.

To ignore this rule on one visual, add { "name": "pbiplint.ignore", "value": "ENSURE_THEME_COLOURS" } to the annotations array of its visual.json. Power BI Desktop keeps the annotation. To turn the rule off for a whole project, set "ENSURE_THEME_COLOURS": "off" under rules in pbiplint.config.json.

Quirks

Ported from PBI Inspector's base rules by Nat Van Gulck.

Check a report for this Improve this page