Skip to content

Bar Chart Conditional Formatting in Power BI

A bar chart that renders every bar in the same shade of blue forces the reader to do the comparison work themselves.

A bar chart that renders every bar in the same shade of blue forces the reader to do the comparison work themselves. Conditional formatting moves that work into the visual: bars change color based on the values they represent, so a glance reveals which categories are above target, below target, or simply larger than the rest.

This tutorial covers the three formatting paths available on a bar chart in Power BI Desktop — color by rules, color by value (gradient), and color driven by a DAX measure — and explains when each one is the right tool. It is aimed at beginners, but the DAX section assumes you can write a basic measure.

The three conditional formatting paths

Power BI exposes conditional formatting for bar chart colors in three ways:

  1. Rules — you define numeric thresholds (for example, above 1,000,000 = green, below = red). Simple, but the thresholds are static text you type into a dialog.
  2. Gradient — Power BI maps the minimum and maximum of the current axis to two colors or a color scale. The mapping recalculates with the filter context, so it always spans the visible range.
  3. Field — a measure returns a color for each bar. This is the most flexible option and the only one that can react to a slicer, a target table, or a prior-year comparison.

A fourth path exists on some visuals (Rules with a “Field” source for the threshold itself), but for bar charts the three above cover almost every real requirement.

Step-by-step: formatting bars with rules

Rules are the fastest way to get colored bars, and they work fine when your thresholds do not change.

  1. Select the bar chart on the canvas.
  2. Open the Format visual pane (the paintbrush icon).
  3. Expand Bars (or Columns if you rotated the chart).
  4. Next to Color, click the fx button. In newer versions the same button appears as a small calculator icon inside the color dropdown.
  5. In the Format style dropdown, choose Rules.
  6. Set Apply to to Color by and pick the field the rules should evaluate — typically your measure, such as Total Sales.
  7. Define the rule: if value is >= and is less than a number, then choose a color. Use + New rule to add more bands.

A common beginner mistake is leaving Summarization on the wrong aggregation. If the rule panel shows Sum of Sales but your chart plots a measure named Total Sales, the rule evaluates a different number than the bar height and the colors will look wrong. Match the field exactly.

Rules are evaluated against the aggregated value per category in the current filter context. They do not consider other bars, so a bar chart of monthly sales with a fixed rule ”> 500K = green” will show exactly the months that passed the bar — no relative logic.

Gradient formatting for relative comparisons

Gradient formatting does the opposite: it ignores absolute thresholds and colors bars relative to the smallest and largest values currently on the axis.

In the same fx dialog, choose Gradient as the format style, then set:

  • Minimum value and color
  • Maximum value and color
  • Optionally a Center value and color for a diverging scale

If you leave minimum and maximum blank, Power BI uses the current range of the data. When a slicer filters the chart down to three months, those three bars re-scale — the largest of the three becomes the “maximum” color. That is usually desirable for a heatmap-style bar chart and usually undesirable if your audience reads color as an absolute signal. Decide which reading you want before you pick gradient.

For a diverging scale (for example, red below target, green above), set the center to your target value and give the low end and high end contrasting colors. This is the cleanest way to build a variance bar chart.

Driving bar color with a DAX measure

The Field option is where conditional formatting stops being cosmetic. When you choose Format style → Field value, Power BI asks for a field or measure that returns a color. The measure must return a valid color string, and it is evaluated in the same filter context as the bar.

The usual pattern is a SWITCH over a comparison:

Bar Color =
VAR Target = 500000
VAR Actual = [Total Sales]
RETURN
    SWITCH(
        TRUE(),
        Actual = BLANK(), "#D9D9D9",
        Actual >= Target * 1.1, "#1F7A3D",
        Actual >= Target, "#8CC63F",
        Actual >= Target * 0.9, "#F5A623",
        "#D0021B"
    )

Two things matter here. First, SWITCH(TRUE(), ...) evaluates conditions in order and returns the first match, so the most specific band must come first. Second, the color strings are hex literals wrapped in quotes — Power BI expects text, not a color object.

You can also return named colors such as "red" or "Green", but hex codes give you control over the exact shade. Avoid returning BLANK() when you actually want a neutral color; blank may fall back to the visual default, which is rarely what you intended. Return an explicit hex value instead.

Making the color react to a slicer

Because the measure is evaluated per category, it already reacts to filters applied to the visual. If a slicer limits the chart to one region, only that region’s bar is drawn and colored. What the measure cannot do on its own is react to a selection made somewhere else on the page, unless the two visuals are related through the filter context. Use Edit interactions if you need a table selection to drive the colors.

Coloring by rank

A frequent request is “color the top 3 bars.” That needs a rank, not a value comparison. The measure below ranks categories by sales and colors the top three:

Top 3 Color =
VAR SalesRank =
    RANKX(
        ALLSELECTED( Products[Category] ),
        [Total Sales],
        ,
        DESC,
        DENSE
    )
RETURN
    IF( SalesRank <= 3, "#1F7A3D", "#BFBFBF" )

ALLSELECTED keeps the ranking inside the current slicer scope, so changing a slicer re-ranks the categories, and DENSE avoids gaps when two categories tie. Note that RANKX needs a table expression as its first argument — passing a single column works, but passing the full table lets the measure include any category present in the filter context.

Rules versus Field: which to choose

SituationBest option
Fixed business thresholds that rarely changeRules
Quick heatmap look, relative to current dataGradient
Thresholds stored in a table or driven by a slicerField (DAX)
Color depends on rank, prior year, or multiple conditionsField (DAX)
One-off visual for a static reportRules or Gradient

If you find yourself typing thresholds into the rules dialog every quarter, move them into a small parameter table and read them with a measure. That single change removes an entire class of report maintenance.

Common pitfalls

  • Wrong field in the rule. The formatting field must be the measure plotted on the axis, not a raw column with a different aggregation.
  • Gradient hiding the signal. When all values are similar, a gradient makes small differences look dramatic. Use a fixed min/max when the comparison should be stable.
  • Text instead of color. A measure that returns a number for the color field silently falls back to the default. Return a string.
  • Palette clashing with the report theme. Custom hex colors ignore the report theme, so a theme change will not update them. If you rely on theming, keep custom colors to a minimum.

FAQ

Q: Can I apply conditional formatting to the data labels as well as the bars?

Yes. In the Format pane, open Data labels, expand Values, and use the same fx dialog on the Color property. You can point labels at the same measure you used for the bars, or a different one if you want the label color to encode something else, such as profit margin.

Q: Why does my DAX color measure return the same color for every bar?

The measure is almost certainly being evaluated without the per-category context you expected — for example, you referenced a column from a table that is not on the axis, or you wrapped the result in CALCULATE with a filter that removes the category filter. Check that the measure references the axis field through the filter context rather than hard-coding a single value.

Q: Do conditional formatting rules work in Power BI Service after publishing?

They carry over with the report file. Rule-based formatting, gradient formatting, and measure-driven color all render in the Service the same way as in Desktop. What does not carry over is any formatting applied through the old Analytics pane preview features, which have been retired.

Q: Can conditional formatting read a target from a table instead of a hard-coded number?

Yes, and this is the main reason to use the Field option. Create a one-row target table, relate or cross-filter it as needed, and replace VAR Target = 500000 with VAR Target = SELECTEDVALUE( Targets[Value] ). The measure then re-colors every bar when the target row changes.