Updated March 2026

Power BI KPI Cards & SVG Visuals: The Complete Guide to Custom Dashboard Indicators

Build enterprise-grade KPI dashboards using the New Card visual, DAX-generated SVG images, and the best AppSource custom visuals. Includes five copy-paste DAX patterns for sparklines, bullet charts, traffic lights, progress bars, and star ratings.

5 DAX SVG PatternsCopy-Paste ReadyEnterprise Best PracticesNew Card Visual Deep Dive

Quick Answer: How Do You Create Custom KPI Visuals in Power BI?

Power BI offers three primary ways to create custom KPI visuals: the built-in New Card visual, DAX-generated SVG images, and AppSource custom visuals. SVG visuals let you create sparklines, bullet charts, traffic lights, and progress bars using pure DAX— no custom visual development required. You write a DAX measure that returns a valid SVG XML string, set the column's data category to "Image URL," and Power BI renders the graphic inline in any table, matrix, or card visual.

The New Card visual (introduced late 2023, significantly updated through 2024-2026) is the recommended starting point for most KPI displays. It supports multiple callout values, reference labels for comparison context, inline images from DAX SVG measures, conditional formatting with rules or field values, and flexible layout options. For most enterprise dashboards, combining the New Card with two or three DAX SVG patterns covers 90% of KPI requirements without any third-party dependencies.

The DAX SVG technique works because Power BI can render images from data URIs. Your measure returns a string like data:image/svg+xml,<svg ...></svg>, and Power BI displays it as a scalable vector graphic. This approach is fully supported in Power BI Desktop, the Power BI Service, Embedded, and Mobile. It responds to slicers and cross-filtering like any other measure, making it ideal for dynamic, context-aware KPI indicators.

At EPC Group, we implement SVG-based KPI dashboards for Fortune 500 clients across healthcare, finance, and government. The five DAX patterns in this guide are the exact patterns our team uses in production. — Errin O'Connor, Chief AI Architect & CEO, EPC Group

KPI Visual Options Comparison

Before diving into implementation, understand your options. Each approach has distinct strengths depending on your requirements for customization, maintenance, and organizational governance. The following table compares the four main approaches to KPI visuals in Power BI.

FeatureLegacy CardNew Card (2024+)SVG via DAXAppSource Custom Visual
Setup ComplexityVery LowLowMedium-HighLow-Medium
Multiple ValuesNo (1 value)Yes (up to 4)UnlimitedVaries
Sparklines / ChartsNoVia SVG imageYes (full control)Yes (if supported)
Conditional FormattingBasic (font, bg)Advanced (rules, field)Unlimited (DAX logic)Varies
Brand CustomizationLimitedModerateCompleteVaries
Mobile SupportYesYesYesMost
IT Admin ApprovalNot neededNot neededNot neededRequired (tenant setting)
Performance ImpactMinimalMinimalModerate (depends on complexity)Varies
Best ForSimple single-value displayMulti-value KPI cardsCustom inline graphics in tables/matricesSpecialized chart types

Our recommendation: Start with the New Card visual for standalone KPI displays. Use DAX SVG for inline indicators in tables and matrices where you need sparklines, progress bars, or status icons next to data rows. Reserve AppSource visuals for specialized chart types (like Deneb for Vega-Lite specifications) where neither the New Card nor SVG provides what you need. This layered approach minimizes external dependencies while maximizing customization. See our dashboard development services for how we apply this in enterprise engagements.

The New Card Visual (2024+): Deep Dive

The New Card visual is Microsoft's replacement for the legacy card. It was introduced in late 2023, reached general availability in 2024, and has received continuous improvements through 2026. If you are still using the legacy card in new reports, switch now — the New Card is strictly superior in every dimension.

Key Capabilities

  • Multiple Callout Values: Display up to four measures in a single card. For example, show Revenue, YoY Growth %, Gross Margin, and Customer Count in one visual instead of four separate cards.
  • Reference Labels: Add static or dynamic text labels that provide context. Common patterns include "vs. Prior Year," "Target: $1.2M," or a DAX measure that returns contextual text like the selected region name.
  • Reference Values: Show a comparison value alongside your primary callout. The reference value can display variance, target, previous period, or any other DAX measure. Pair it with conditional formatting to color the reference green for positive variance and red for negative.
  • Inline Images: The New Card supports the Image data category, which means you can embed a DAX SVG measure directly inside the card. This enables sparklines, trend arrows, and mini-charts within the card layout.
  • Layout Options: Choose between horizontal and vertical arrangements for callout values. Add accent bars (top, bottom, left, right) with custom colors. Use dividers between values for visual separation.
  • Conditional Formatting: Apply rules-based or field-value-based formatting to callout values, reference values, background, accent bars, and font colors. Field-value formatting is the most powerful: create a DAX measure that returns a hex color code and bind it to any formatting property.

Setting Up the New Card

To configure the New Card visual, follow these steps. First, add a "New card" visual from the Visualizations pane (it is labeled "Card (new)" in recent versions). Drag your primary KPI measure to the Callout value well. In the Format pane, expand Callout values to adjust font size, color, and display units. Add a reference label by expanding Reference labels and typing your label text or binding it to a measure. Add a reference value by dragging a comparison measure to the Reference valuewell — this is where you would put a "vs Target" or "YoY Change" measure.

For conditional formatting on the reference value: select the reference value field, click the fxbutton next to Font Color, choose "Field value," and bind it to a DAX measure that returns color codes. A common pattern:

Reference Color =
IF(
    [YoY Growth %] >= 0,
    "#22C55E",   // Green for positive
    "#EF4444"    // Red for negative
)

This approach gives you dynamic KPI cards that change color based on live data without any custom development. For more advanced KPI card layouts with embedded sparklines, continue to the DAX SVG section below.

DAX-Generated SVG Visuals: The Technique

DAX SVG is the most powerful and flexible approach to custom KPI visuals in Power BI. The concept is straightforward: write a DAX measure that constructs a valid SVG XML string, then display that measure in a visual that supports the Image data category. Power BI renders the SVG as a scalable vector graphic that responds to all filter context.

How It Works

  1. Create a DAX measure that returns a string beginning with "data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' ...>"
  2. Set the data category of the measure (or the column used to display it) to Image URL in the modeling tab.
  3. Add the measure to a Table, Matrix, or New Card visual. Power BI interprets the data URI and renders the SVG inline.

The key insight is that Power BI's Image URL feature accepts data: URIs, not just https:// URLs. This means you can dynamically generate the image content in DAX. The SVG format is ideal because it is text-based (so DAX string concatenation works), scalable (crisp at any resolution), and lightweight (small string size compared to base64-encoded PNGs).

Below are five production-ready DAX SVG patterns that our DAX optimization team deploys in enterprise dashboards. Each includes complete DAX code, an explanation of the SVG structure, and implementation instructions.

Pattern 1: Traffic Light Indicator

Red/yellow/green circle based on threshold values. Perfect for status columns in tables and matrices.

Traffic Light =
VAR _Value = [KPI Score]
VAR _Color =
    SWITCH(
        TRUE(),
        _Value >= 80, "#22C55E",   // Green: on target
        _Value >= 50, "#F59E0B",   // Amber: needs attention
        "#EF4444"                   // Red: critical
    )
VAR _Label =
    SWITCH(
        TRUE(),
        _Value >= 80, "On Track",
        _Value >= 50, "At Risk",
        "Critical"
    )
RETURN
"data:image/svg+xml," &
"<svg xmlns='http://www.w3.org/2000/svg' width='120' height='30'>" &
    "<circle cx='15' cy='15' r='12' fill='" & _Color & "' />" &
    "<text x='35' y='20' font-family='Segoe UI,sans-serif' font-size='13' fill='%23374151'>" &
        _Label &
    "</text>" &
"</svg>"

SVG structure: A 120x30 viewport containing a filled circle at (15,15) with radius 12, plus a text label positioned to the right. The circle color and label text are both driven by the [KPI Score] measure using a SWITCH/TRUE pattern with three thresholds.

Implementation: Create the measure, go to the Modeling tab, set Data Category to "Image URL." Add the measure to a Table or Matrix visual. The traffic light will appear inline in each row, dynamically changing based on the row's filter context. Note: use %23 instead of # for hex colors inside SVG text elements when using the data URI approach, as the hash character can cause parsing issues. For circle fill colors, the hash works because it is inside an attribute value.

Pattern 2: Horizontal Progress Bar

Percentage fill bar with value label. Ideal for completion tracking, budget utilization, and target achievement.

Progress Bar =
VAR _Pct = MIN( [Completion %], 1 )  // Cap at 100%
VAR _PctDisplay = FORMAT( _Pct, "0%" )
VAR _BarWidth = ROUND( _Pct * 200, 0 )
VAR _BarColor =
    SWITCH(
        TRUE(),
        _Pct >= 0.9, "#22C55E",
        _Pct >= 0.6, "#3B82F6",
        _Pct >= 0.3, "#F59E0B",
        "#EF4444"
    )
RETURN
"data:image/svg+xml," &
"<svg xmlns='http://www.w3.org/2000/svg' width='260' height='28'>" &
    "<!-- Background bar -->" &
    "<rect x='0' y='6' width='200' height='16' rx='8' fill='%23E5E7EB' />" &
    "<!-- Fill bar -->" &
    "<rect x='0' y='6' width='" & _BarWidth & "' height='16' rx='8' fill='" & _BarColor & "' />" &
    "<!-- Percentage label -->" &
    "<text x='210' y='20' font-family='Segoe UI,sans-serif' font-size='13' font-weight='600' fill='%23374151'>" &
        _PctDisplay &
    "</text>" &
"</svg>"

SVG structure: A 260x28 viewport with two overlapping rounded rectangles: a gray background bar (200px wide) and a colored fill bar whose width is calculated from the percentage. The percentage text label sits to the right of the bar. The rx='8' attribute rounds the rectangle corners for a modern appearance.

Implementation: The MIN( [Completion %], 1 ) prevents the bar from overflowing if values exceed 100%. The color shifts from red through amber and blue to green as completion increases. For budget utilization dashboards where exceeding 100% is a warning, invert the color logic so that values above 90% turn red. Adjust the bar width (200px) and viewport width (260px) to fit your table column widths.

Pattern 3: Sparkline Chart (Last 12 Months)

A mini trend line showing the last 12 months of data. The most requested SVG pattern for enterprise tables.

Sparkline SVG =
VAR _Dates =
    FILTER(
        ALLSELECTED( 'Calendar'[YearMonth] ),
        'Calendar'[YearMonth] >= FORMAT(
            EDATE( MAX( 'Calendar'[Date] ), -11 ), "YYYY-MM"
        )
    )
VAR _Values =
    ADDCOLUMNS(
        _Dates,
        "@Val", CALCULATE( [Revenue], 'Calendar'[YearMonth] = [YearMonth] )
    )
VAR _Min = MINX( _Values, [@Val] )
VAR _Max = MAXX( _Values, [@Val] )
VAR _Range = IF( _Max - _Min = 0, 1, _Max - _Min )
// SVG dimensions
VAR _Width = 200
VAR _Height = 40
VAR _Padding = 4
VAR _PlotH = _Height - _Padding * 2
VAR _PlotW = _Width - _Padding * 2
VAR _Count = COUNTROWS( _Values )
VAR _Step = DIVIDE( _PlotW, _Count - 1, 0 )
// Build polyline points string
VAR _Points =
    CONCATENATEX(
        ADDCOLUMNS(
            ADDCOLUMNS(
                _Values,
                "@Idx", RANKX( _Values, [YearMonth], , ASC, DENSE ) - 1
            ),
            "@X", _Padding + [@Idx] * _Step,
            "@Y", _Padding + _PlotH - DIVIDE( [@Val] - _Min, _Range, 0 ) * _PlotH
        ),
        FORMAT( [@X], "0.0" ) & "," & FORMAT( [@Y], "0.0" ),
        " ",
        [@Idx], ASC
    )
// Last value for end dot
VAR _LastVal = MAXX( TOPN( 1, _Values, [YearMonth], DESC ), [@Val] )
VAR _LastX = _Padding + ( _Count - 1 ) * _Step
VAR _LastY = _Padding + _PlotH - DIVIDE( _LastVal - _Min, _Range, 0 ) * _PlotH
VAR _LineColor = IF( _LastVal >= _Min + _Range * 0.5, "%233B82F6", "%23EF4444" )
RETURN
"data:image/svg+xml," &
"<svg xmlns='http://www.w3.org/2000/svg' width='" & _Width & "' height='" & _Height & "'>" &
    "<polyline points='" & _Points & "' fill='none' stroke='" & _LineColor & "' stroke-width='2' />" &
    "<circle cx='" & FORMAT(_LastX, "0.0") & "' cy='" & FORMAT(_LastY, "0.0") & "' r='3' fill='" & _LineColor & "' />" &
"</svg>"

SVG structure: A polyline element plots normalized data points across a 200x40 viewport. Each point is calculated by ranking the YearMonth values, computing X positions at equal intervals, and mapping Y positions by normalizing each value between the minimum and maximum of the 12-month window. A circle marks the most recent data point. The line color is blue if the latest value is in the upper half of the range, red if in the lower half.

Implementation: This pattern requires a Calendar table with a YearMonth column in "YYYY-MM" format. The ALLSELECTED function respects page-level filters while iterating across the 12 months. Set the measure's data category to Image URL and add it to a table or matrix. Each row generates its own sparkline based on its filter context, so in a matrix with Product rows, each product gets a unique sparkline. See our star schema modeling guide for best practices on Calendar table design.

Pattern 4: Bullet Chart (Actual vs Target)

Shows actual performance against a target with qualitative range bands (poor, satisfactory, good). A compact alternative to full-size bar charts.

Bullet Chart =
VAR _Actual = [Revenue]
VAR _Target = [Revenue Target]
VAR _Max = MAX( _Actual, _Target ) * 1.2  // 20% headroom
// Normalize to 200px width
VAR _Scale = DIVIDE( 200, _Max, 0 )
VAR _ActualW = ROUND( _Actual * _Scale, 0 )
VAR _TargetX = ROUND( _Target * _Scale, 0 )
// Range bands: 60% = poor, 80% = satisfactory, 100% = good
VAR _PoorW = ROUND( _Max * 0.6 * _Scale, 0 )
VAR _SatW = ROUND( _Max * 0.8 * _Scale, 0 )
VAR _GoodW = 200
RETURN
"data:image/svg+xml," &
"<svg xmlns='http://www.w3.org/2000/svg' width='220' height='30'>" &
    "<!-- Range bands -->" &
    "<rect x='0' y='2' width='" & _GoodW & "' height='26' fill='%23D1D5DB' />" &
    "<rect x='0' y='2' width='" & _SatW & "' height='26' fill='%239CA3AF' />" &
    "<rect x='0' y='2' width='" & _PoorW & "' height='26' fill='%236B7280' />" &
    "<!-- Actual bar -->" &
    "<rect x='0' y='8' width='" & _ActualW & "' height='14' fill='%233B82F6' />" &
    "<!-- Target marker -->" &
    "<line x1='" & _TargetX & "' y1='2' x2='" & _TargetX & "' y2='28' stroke='%23111827' stroke-width='2.5' />" &
"</svg>"

SVG structure: Three overlapping gray rectangles create qualitative range bands (darker = worse performance zone). A blue rectangle shows actual performance, narrower in height than the range bands so both are visible. A vertical black line marks the target. The entire chart fits in a 220x30 viewport suitable for table columns.

Implementation: Replace [Revenue] and [Revenue Target] with your actual and target measures. The 60%/80%/100% band thresholds are configurable — adjust them to match your organization's performance benchmarks. For a color-coded actual bar, add a SWITCH/TRUE pattern similar to the progress bar pattern to change the blue fill based on performance ratio. The _Max * 1.2 provides 20% headroom so values near the target are not visually compressed against the edge.

Pattern 5: Star Rating (1-5 Stars)

Visual star rating based on a score. Great for customer satisfaction, product ratings, and quality scores.

Star Rating =
VAR _Score = [Customer Rating]  // Expects 0-5
VAR _Rounded = ROUND( _Score, 0 )
// Star SVG path (a 5-pointed star)
VAR _StarPath = "M10,1 L12.9,7 L19.5,7.6 L14.5,12 L16,18.5 L10,15 L4,18.5 L5.5,12 L0.5,7.6 L7.1,7 Z"
VAR _Star1Fill = IF( _Rounded >= 1, "%23F59E0B", "%23D1D5DB" )
VAR _Star2Fill = IF( _Rounded >= 2, "%23F59E0B", "%23D1D5DB" )
VAR _Star3Fill = IF( _Rounded >= 3, "%23F59E0B", "%23D1D5DB" )
VAR _Star4Fill = IF( _Rounded >= 4, "%23F59E0B", "%23D1D5DB" )
VAR _Star5Fill = IF( _Rounded >= 5, "%23F59E0B", "%23D1D5DB" )
RETURN
"data:image/svg+xml," &
"<svg xmlns='http://www.w3.org/2000/svg' width='130' height='20' viewBox='0 0 130 20'>" &
    "<g transform='translate(0,0) scale(0.95)'>" &
        "<path d='" & _StarPath & "' fill='" & _Star1Fill & "' />" &
    "</g>" &
    "<g transform='translate(22,0) scale(0.95)'>" &
        "<path d='" & _StarPath & "' fill='" & _Star2Fill & "' />" &
    "</g>" &
    "<g transform='translate(44,0) scale(0.95)'>" &
        "<path d='" & _StarPath & "' fill='" & _Star3Fill & "' />" &
    "</g>" &
    "<g transform='translate(66,0) scale(0.95)'>" &
        "<path d='" & _StarPath & "' fill='" & _Star4Fill & "' />" &
    "</g>" &
    "<g transform='translate(88,0) scale(0.95)'>" &
        "<path d='" & _StarPath & "' fill='" & _Star5Fill & "' />" &
    "</g>" &
    "<text x='115' y='15' font-family='Segoe UI,sans-serif' font-size='12' fill='%23374151'>" &
        FORMAT( _Score, "0.0" ) &
    "</text>" &
"</svg>"

SVG structure: Five star shapes drawn using an SVG path definition, each translated 22 pixels to the right. Stars are filled amber (#F59E0B) up to the rounded score and gray (#D1D5DB) beyond it. The numeric score displays to the right of the stars. The viewBox attribute ensures consistent scaling.

Implementation: The [Customer Rating] measure should return a value between 0 and 5. For half-star support, you would need to use SVG clipPath or linearGradient elements to partially fill stars, which adds complexity but is achievable. For most enterprise use cases, whole-star rounding is sufficient and keeps the DAX simpler. This pattern works well in product review dashboards, vendor scorecards, and employee performance tables.

Enterprise Branding with SVG

One of the strongest arguments for DAX SVG visuals in enterprise environments is brand consistency. Unlike built-in conditional formatting where you are limited to predefined icons and a color picker, SVG gives you pixel-perfect control over every color, shape, and dimension. Here is how to implement a brand-consistent SVG template system.

DAX Variables for Brand Colors

Create a centralized set of DAX measures for your brand palette. Reference these in all SVG measures to ensure consistency across every visual in the report:

// Create these as measures in a "Brand Config" table
Brand Primary = "%230F172A"       // Dark navy
Brand Secondary = "%233B82F6"     // Blue
Brand Success = "%2322C55E"       // Green
Brand Warning = "%23F59E0B"       // Amber
Brand Danger = "%23EF4444"        // Red
Brand Neutral = "%23D1D5DB"       // Light gray
Brand Font = "Segoe UI,sans-serif"

// Usage in any SVG measure:
Branded Progress Bar =
VAR _Pct = [Completion %]
VAR _Color = [Brand Secondary]
VAR _BgColor = [Brand Neutral]
VAR _Font = [Brand Font]
RETURN
"data:image/svg+xml," &
"<svg xmlns='http://www.w3.org/2000/svg' width='200' height='24'>" &
    "<rect width='200' height='16' y='4' rx='8' fill='" & _BgColor & "' />" &
    "<rect width='" & ROUND(_Pct * 200, 0) & "' height='16' y='4' rx='8' fill='" & _Color & "' />" &
"</svg>"

This pattern means that if your organization rebrands, you update the color measures once and every SVG visual across every page of every report updates automatically. No hunting through conditional formatting rules or visual settings.

For organizations with multiple brands or client-specific reports, store brand colors in a configuration table and use LOOKUPVALUE to dynamically select the correct palette based on a slicer or parameter. This is a technique we implement frequently at EPC Group's dashboard development practice for multi-tenant reporting platforms. Check out our dashboard examples for live demonstrations.

Performance Considerations: SVG at Scale

DAX SVG visuals are not free from a performance perspective. Every SVG is a string stored in memory during query execution and rendered by the browser. Understanding the performance implications ensures your dashboards remain responsive at enterprise data volumes.

VertiPaq Storage Impact

SVG measures are calculated at query time and not stored in the VertiPaq engine like columns, so they do not increase your model size. However, the formula engine must evaluate the SVG string for every row in the visual's result set. A table with 500 rows, each generating a sparkline that iterates over 12 months of data, means 6,000 CALCULATE evaluations just for the sparkline column. The formula engine processes these sequentially (single-threaded), so complex SVG measures can become the bottleneck.

Performance Guidelines

  • Keep row counts manageable: SVG measures work best in tables and matrices with fewer than 200-300 visible rows. Use Top N filtering or pagination if your dataset is larger.
  • Simplify sparkline iterations: 12 data points per sparkline is the sweet spot. Going beyond 24 points rarely adds visual insight but doubles the computation. Never iterate over daily data for sparklines; aggregate to weekly or monthly first.
  • Avoid SVG in DirectQuery mode: DirectQuery models re-query the source for every interaction. Complex SVG measures that depend on multiple CALCULATE calls will send many queries to the source database. Use Import mode or consider Composite models with the SVG-related tables in Import mode.
  • SVG string length: Keep SVG strings under 2,000 characters. The sparkline pattern above generates approximately 500-800 characters depending on data point count. If your SVG exceeds 2,000 characters, consider simplifying the visual or splitting it into multiple measures.
  • Test with Performance Analyzer: In Power BI Desktop, use View > Performance Analyzer to measure the DAX query time for visuals containing SVG measures. If a single visual takes more than 2 seconds, optimize the underlying measures or reduce the row count.

In practice, the five patterns in this guide are well within performance bounds for typical enterprise dashboards (50-200 row tables with 1-3 SVG columns). Performance issues typically arise when combining SVG measures with already-complex DAX calculations on large fact tables. Our DAX optimization services can help identify and resolve these bottlenecks.

Conditional Formatting Deep Dive

Conditional formatting and SVG visuals are complementary techniques, not competitors. Understanding when to use each approach — and how to combine them — is key to building effective KPI dashboards.

Built-in Conditional Formatting Options

Power BI provides six conditional formatting channels for table and matrix visuals:

  • 1.Background Color: Applies a fill color to the cell. Supports rules (if value between X and Y), field value (DAX measure returns hex code), and gradient scale (min-to-max color transition). Best for heat maps and status highlighting.
  • 2.Font Color: Changes the text color. Same three options as background. Use with background color for high-contrast status indicators (e.g., white text on red background for critical items).
  • 3.Data Bars: Adds a proportional bar behind the cell value, similar to Excel's data bars. Limited customization but zero DAX overhead. Good for simple relative comparisons.
  • 4.Icons: Displays a small icon next to the value from a predefined set (arrows, flags, circles, etc.). Limited to Microsoft's icon library — cannot use custom icons. This is where SVG visuals offer a massive advantage.
  • 5.Web URL: Makes the cell value a clickable hyperlink. Can be combined with SVG — the SVG image becomes the clickable element.
  • 6.Image URL: Renders an image from a URL or data URI. This is the channel that enables DAX SVG visuals. Set a measure as the Image URL source to display inline SVGs.

Rules vs Field Value vs Gradient

Rules:Define explicit ranges (e.g., "if value is 0 to 50, apply red; if 50 to 80, apply yellow; if 80 to 100, apply green"). Rules are static and must be manually updated if thresholds change. Best for simple, fixed-threshold KPIs.

Field Value: Bind the formatting property to a DAX measure that returns a color string (e.g., "#22C55E"). The most powerful option because your DAX measure can implement any logic: compare to dynamic targets, use percentiles, reference other tables, or apply different thresholds per product/region. Always prefer field value over rules when thresholds are dynamic or when you have more than three color bands.

Gradient: Automatically creates a smooth color transition from minimum to maximum values. Specify a minimum color, midpoint color, and maximum color. Power BI interpolates between them. Best for heat maps, geographic intensity displays, and continuous metrics without discrete thresholds.

When to Use SVG Instead of Conditional Formatting

Use DAX SVG when you need: custom shapes beyond circles and arrows (progress bars, sparklines, bullet charts), multiple visual elements in a single cell (a traffic light plus label text), precise dimensional control (exact pixel widths for progress bars), brand-specific iconography, or any visual that Power BI's built-in icons and formatting cannot express. Use conditional formatting when you only need color changes on existing values — it is simpler, faster to implement, and has zero performance overhead compared to SVG string generation.

AppSource Custom Visuals Worth Using

When the New Card and DAX SVG do not cover your requirements, AppSource offers certified custom visuals vetted by Microsoft. Here are the five enterprise-safe KPI visuals we recommend for organizations with strict governance requirements.

1. Deneb (Vega-Lite)

Microsoft Certified | Free | Actively Maintained

Deneb brings the full power of the Vega-Lite visualization grammar into Power BI. You write a JSON specification that describes your visual, and Deneb renders it. This gives you access to hundreds of chart types not available in Power BI natively: bump charts, beeswarm plots, waffle charts, unit charts, and highly customized KPI displays. Deneb is the most flexible custom visual available but has the steepest learning curve. Use it when your KPI requirements go beyond what DAX SVG can reasonably express — for example, animated transitions, interactive tooltips within the custom visual, or chart types that require axis scales and legends.

2. HTML Content

Community Visual | Free | By Daniel Marsh-Patrick

The HTML Content visual renders HTML and SVG from a DAX measure. Unlike the native Image URL approach, HTML Content supports full HTML layout including divs, flexbox, CSS styling, and multiple SVG elements in a single visual. Use it when you need a complex KPI card layout that combines text, numbers, and SVG graphics in a specific arrangement that the New Card visual cannot achieve. Note: HTML Content is not Microsoft-certified, so check your organization's tenant settings for custom visual policies before deploying.

3. Charticulator

Microsoft Certified | Free | By Microsoft Research

Charticulator is a drag-and-drop custom chart designer developed by Microsoft Research. You design your visual interactively by mapping data fields to visual properties (position, size, color, shape), and Charticulator generates a reusable custom visual. It excels at creating unique chart types that are difficult to code manually: radial bar charts, pictograph unit charts, and custom KPI layouts with precise spatial control. The visual you design can be exported as a .pbiviz file and shared across reports. Best for teams that need custom visuals but lack developers to build them from scratch.

4. Bullet Chart by OKViz

Microsoft Certified | Free Tier Available | Enterprise License Available

If you need bullet charts without writing DAX SVG, OKViz's Bullet Chart visual is the gold standard. It displays actual values against targets with qualitative range bands, supports multiple orientations (horizontal, vertical), category grouping, and comprehensive formatting options. The certified version integrates with Power BI's tooltip pages and cross-filtering. Use it when you have many bullet charts to display and the DAX SVG approach would create too much measure maintenance overhead, or when non-technical report authors need to configure bullet charts without touching DAX.

5. Card with States by OKViz

Microsoft Certified | Free Tier Available | Enterprise License Available

Card with States extends the card concept with visual state indicators — the card's appearance changes based on the value meeting defined thresholds. It supports text formatting, alignment, padding, background images, and state-based color transitions. Use it as a direct replacement for the legacy KPI visual when you need simple actual-vs-target display with color-coded states but do not want to write DAX SVG measures. It is particularly useful for executive dashboards where the KPI card is the primary visual and needs to look polished with minimal configuration.

Governance note: Before deploying any AppSource visual to production, verify it is Microsoft Certified (look for the blue checkmark on AppSource), test it with your Row-Level Security configuration, confirm it works in Power BI Embedded if you use that deployment model, and validate export behavior (PDF, PowerPoint). Our Power BI consulting team can audit your visual selection for enterprise readiness.

Common Mistakes to Avoid

After implementing DAX SVG visuals across dozens of enterprise deployments, these are the five mistakes we see most frequently. Each one can cause anything from broken visuals to crashed reports.

Mistake 1: SVG Too Complex, Crashing Reports

When a sparkline iterates over 365 daily data points instead of 12 monthly aggregates, the SVG string can exceed 10,000 characters per row. Multiply that by 200 rows in a table and you are generating 2MB of SVG strings per visual refresh. This overwhelms the browser's rendering engine and can freeze or crash the report. Fix: Always aggregate data to the coarsest granularity that communicates the trend. For sparklines, 12 monthly points or 13 weekly points is the maximum you should ever need. Pre-aggregate in the model, not in the SVG measure.

Mistake 2: Not URL-Encoding SVG Characters

The # character in hex color codes has special meaning in URLs (it denotes a fragment identifier). Inside a data:image/svg+xml, URI, unencoded # characters can cause the SVG to be truncated at that point. Fix: Replace # with %23 in all color values used in SVG text and attributes. Inside fill and stroke attributes within quoted values, # generally works, but using %23 everywhere is the safest approach.

Mistake 3: Wrong Image Column Data Category

You write a perfectly valid SVG measure but only see the raw string text in your visual instead of a rendered image. This happens when the column or measure is not set to the Image URL data category. Fix:Select the measure in the model view, go to Column Tools (or Measure Tools), and set Data Category to "Image URL." For calculated columns, the setting is in Column Properties. This is a one-time setting per measure but is easy to forget when creating new SVG measures.

Mistake 4: Using Conditional Formatting When SVG is Better

Report authors sometimes build elaborate multi-rule conditional formatting with five or six color bands, custom icon sets, and background gradients when a single SVG measure would be cleaner and more maintainable. Fix: If you find yourself creating more than three conditional formatting rules on a single column, consider switching to an SVG visual. The SVG approach centralizes all logic in one DAX measure, making it easier to document, version control, and modify. Conditional formatting rules are stored in the visual configuration (not in DAX), making them harder to audit and replicate across reports.

Mistake 5: Not Testing on Mobile

SVG visuals that look perfect on desktop can break on Power BI Mobile due to different viewport handling and image size constraints. Small SVG viewports (like a 120x20 traffic light) may render too small to read on mobile screens. Fix: Always test SVG visuals in the Power BI Mobile app before deploying to production. Consider creating a dedicated mobile layout in Power BI Desktop and using larger SVG viewports (e.g., 200x40 instead of 120x20) for visuals that will appear on mobile. The New Card visual handles mobile responsiveness better than raw SVG in tables, so prefer cards over table-embedded SVG for mobile-first dashboards.

Ready to Transform Your Data Strategy?

Get a free consultation to discuss how Power BI and Microsoft Fabric can drive insights and growth for your organization.

Frequently Asked Questions

What is an SVG visual in Power BI?

An SVG visual in Power BI is a Scalable Vector Graphics image generated dynamically using DAX. You write a DAX measure that returns a valid SVG XML string, set the column data category to Image URL, and Power BI renders the SVG inline. This technique lets you create sparklines, traffic lights, progress bars, bullet charts, and star ratings using pure DAX without installing any custom visuals or leaving the standard Power BI environment. SVG visuals scale perfectly at any resolution and respond dynamically to filter context, slicers, and cross-filtering just like any other measure.

How do I create a KPI card in Power BI?

To create a KPI card in Power BI, use the New Card visual introduced in late 2023. Add a New Card from the Visualizations pane, drag your primary measure to the Callout value field, add a reference label for context like Previous Period or Target, and optionally add a reference value that shows comparison data. You can add conditional formatting to change colors based on performance thresholds. For more advanced KPI cards, combine the New Card with DAX-generated SVG images to embed sparklines, trend arrows, or traffic light indicators directly within the card. The New Card visual supports up to four callout values, reference labels, and inline images.

Can I create sparklines in Power BI without custom visuals?

Yes, you can create sparklines in Power BI without any custom visuals using DAX-generated SVG. You write a DAX measure that iterates over your date table, calculates the value for each period, normalizes the values to fit within an SVG viewBox, and constructs an SVG polyline or path element. The measure returns a complete SVG string that Power BI renders as an inline image. This approach works in tables, matrices, and the New Card visual. The sparkline updates dynamically based on the current filter context. The only limitation is performance: if you have thousands of rows each generating a complex SVG, rendering time can increase.

What is the difference between the old and new card visual in Power BI?

The old card visual (legacy) displays a single value with a category label and supports basic conditional formatting for font color and background. The New Card visual, introduced in late 2023 and updated through 2024-2026, supports multiple callout values in a single card, reference labels and reference values for comparison context, inline images from SVG or URL, advanced layout options including horizontal and vertical arrangements, accent bars and dividers, and richer conditional formatting. The New Card also supports the Image data category, allowing you to embed DAX-generated SVG visuals directly inside the card for sparklines, icons, and indicators. Microsoft recommends using the New Card for all new reports.

Do SVG visuals work in Power BI Service?

Yes, DAX-generated SVG visuals work in Power BI Service (app.powerbi.com), Power BI Embedded, and Power BI Mobile. The SVG is rendered client-side in the browser or mobile app. However, there are important considerations: SVG visuals in exported PDFs may not render correctly in all cases, email subscriptions with SVG visuals may show placeholder images, and performance in the Service depends on the complexity of the SVG and the number of rows generating SVGs. For paginated reports (SSRS/Power BI Report Builder), SVG support is limited. Always test your SVG visuals in the Service environment before deploying to production.

Are DAX-generated SVG visuals supported by Microsoft?

DAX-generated SVG visuals use a supported feature: the Image URL data category for columns and measures. Microsoft officially supports the ability to display images from URLs and data URIs in table, matrix, and card visuals. The SVG technique leverages this by returning a data URI or inline SVG string from a DAX measure. While Microsoft does not provide official documentation specifically for DAX-to-SVG patterns, the underlying mechanism is fully supported and has been stable since its introduction. Many Microsoft MVPs and the Power BI community actively use and recommend this technique for enterprise dashboards.

How do I add conditional formatting to KPI cards?

Power BI offers several conditional formatting options for KPI cards. In the New Card visual, select the measure in the Visualizations pane, click the fx button next to any formatting property, and choose from: Rules (if value is between X and Y, apply color), Field Value (use a measure to return the color), or Gradient (smooth color transition between min and max). You can apply conditional formatting to background color, font color, and icons. For more advanced conditional formatting, use DAX-generated SVG visuals where you have complete control over colors, shapes, and layout. The SVG approach lets you create traffic lights, progress bars, and custom icons that change based on any business logic you can express in DAX.

What are the best custom KPI visuals on AppSource?

The top enterprise-safe KPI visuals on AppSource are: Deneb (certified, uses Vega-Lite grammar for unlimited visual customization), HTML Content by Daniel Marsh-Patrick (displays HTML and SVG from measures), Charticulator by Microsoft Research (drag-and-drop custom chart builder), Bullet Chart by OKViz (certified, shows actual vs target with qualitative ranges), and Card with States by OKViz (certified, shows KPI cards with conditional state indicators). When selecting AppSource visuals for enterprise use, prioritize Microsoft-certified visuals, check that the visual is actively maintained, verify it works with your Row-Level Security configuration, and test performance with your data volume before deploying to production.

Related Power BI Resources

Need Help Building KPI Dashboards?

Our team has built SVG-powered KPI dashboards for Fortune 500 companies across healthcare, finance, and government. Whether you need a custom dashboard from scratch or optimization of existing reports, we deliver enterprise-grade Power BI solutions with measurable ROI.