DAX SVG measure · Trend

Area sparkline in Power BI with a DAX SVG measure

An area sparkline adds weight under the line, which makes direction easier to read at a glance in a dense table. The choice that matters is the baseline: from the lowest value it shows shape; from zero it shows magnitude and stops small wobbles from looking like crashes.

By · Founder & Reliability Engineer · Updated

Sparkline (area) rendered from the DAX below with sample data
Rendered from the measure below with sample data at 2× (120×32 px in Power BI). 613 characters.

Use it when

  • Rows are scanned quickly and you want rising and falling trends to stand out by colour.
  • The measure is always positive (revenue, volume) and a zero baseline is honest.
  • You want a softer, more editorial look than a single line.

Skip it when

The values cross zero often (variances, net flows): a filled area against a minimum baseline then exaggerates noise. Use win/loss bars or a line sparkline.

Three looks

The sparkline (area) in three palettes; click one to edit it.

Data it needs

The builder asks for exactly these fields; type your own measure and column names there.

Value measure
A measure that is mostly positive. With the zero baseline, negative values fill downward from zero.
Axis column
A date or numeric column; the polygon closes along the baseline at the first and last points.

The full DAX

Swap [Sales] and 'Date'[Month Start] for your own names.

Sparkline Area (measure)
Sparkline Area =
-- VizForge SVG measure: area sparkline.
-- Set Measure tools > Data category = Image URL. Put it in a table or matrix next to a category column.
-- The axis must be a date or number column so points are spaced in time order.
-- Made with the free VizForge SVG measure builder: vizforge.ai/tools/svg-measure-builder
-- Need per-point tooltips, click-to-select inside the chart or Format-pane settings? Generate it as a real custom visual: vizforge.ai/visuals
VAR _Base = FILTER (
    ADDCOLUMNS (
        ALLSELECTED ( 'Date'[Month Start] ),
        "@x", CONVERT ( 'Date'[Month Start], DOUBLE ),
        "@v", [Sales]
    ),
    NOT ISBLANK ( [@v] )
)
VAR _XMin = MINX ( _Base, [@x] )
VAR _XMax = MAXX ( _Base, [@x] )
VAR _Lo = MINX ( _Base, [@v] )
VAR _Hi = MAXX ( _Base, [@v] )
VAR _Floor = FORMAT ( 28.5, "0.0", "en-US" )
VAR _Points = CONCATENATEX (
    _Base,
    FORMAT ( 3.5 + DIVIDE ( [@x] - _XMin, _XMax - _XMin, 0.5 ) * 113, "0.0", "en-US" )
            & ","
            & FORMAT ( 3.5 + ( 1 - DIVIDE ( [@v] - _Lo, _Hi - _Lo, 0.5 ) ) * 25, "0.0", "en-US" ),
    " ",
    [@x], ASC
)
VAR _First = MAXX ( TOPN ( 1, _Base, [@x], ASC ), [@v] )
VAR _Last = MAXX ( TOPN ( 1, _Base, [@x], DESC ), [@v] )
RETURN
    IF (
        COUNTROWS ( _Base ) < 2,
        BLANK (),
        "data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='120' height='32' viewBox='0 0 120 32'><polygon fill='%23118DFF' fill-opacity='0.2' stroke='none' points='"
            & MAXX ( TOPN ( 1, _Base, [@x], ASC ), FORMAT ( 3.5 + DIVIDE ( [@x] - _XMin, _XMax - _XMin, 0.5 ) * 113, "0.0", "en-US" ) )
            & ","
            & _Floor
            & " "
            & _Points
            & " "
            & MAXX ( TOPN ( 1, _Base, [@x], DESC ), FORMAT ( 3.5 + DIVIDE ( [@x] - _XMin, _XMax - _XMin, 0.5 ) * 113, "0.0", "en-US" ) )
            & ","
            & _Floor
            & "'/><polyline fill='none' stroke='%23118DFF' stroke-width='1.5' stroke-linejoin='round' stroke-linecap='round' points='"
            & _Points
            & "'/><circle cx='"
            & MAXX ( TOPN ( 1, _Base, [@x], DESC ), FORMAT ( 3.5 + DIVIDE ( [@x] - _XMin, _XMax - _XMin, 0.5 ) * 113, "0.0", "en-US" ) )
            & "' cy='"
            & FORMAT ( 3.5 + ( 1 - DIVIDE ( _Last - _Lo, _Hi - _Lo, 0.5 ) ) * 25, "0.0", "en-US" )
            & "' r='2.6' fill='%23118DFF'/></svg>"
    )
DAX user-defined function variant (VizForge.SvgSparklineArea)

One-line call: Sparkline Area = VizForge.SvgSparklineArea ( [Sales], 'Date'[Month Start] )

DAX query view script
-- 1) Paste into DAX query view and choose 'Update model with changes'.
--    Needs DAX user-defined functions (generally available since the June 2026 Power BI release).
DEFINE
    /// Sparkline (area) as an SVG image URL (VizForge). Optional parameters default to the colours you picked.
    FUNCTION VizForge.SvgSparklineArea = (
            pValue : ANYREF EXPR,
            pAxis : ANYREF EXPR,
            pLineColor : STRING = "#118DFF"
        ) =>
        VAR _Base = FILTER (
            ADDCOLUMNS (
                ALLSELECTED ( pAxis ),
                "@x", CONVERT ( pAxis, DOUBLE ),
                "@v", CALCULATE ( pValue )
            ),
            NOT ISBLANK ( [@v] )
        )
        VAR _XMin = MINX ( _Base, [@x] )
        VAR _XMax = MAXX ( _Base, [@x] )
        VAR _Lo = MINX ( _Base, [@v] )
        VAR _Hi = MAXX ( _Base, [@v] )
        VAR _Floor = FORMAT ( 28.5, "0.0", "en-US" )
        VAR _Points = CONCATENATEX (
            _Base,
            FORMAT ( 3.5 + DIVIDE ( [@x] - _XMin, _XMax - _XMin, 0.5 ) * 113, "0.0", "en-US" )
                    & ","
                    & FORMAT ( 3.5 + ( 1 - DIVIDE ( [@v] - _Lo, _Hi - _Lo, 0.5 ) ) * 25, "0.0", "en-US" ),
            " ",
            [@x], ASC
        )
        VAR _First = MAXX ( TOPN ( 1, _Base, [@x], ASC ), [@v] )
        VAR _Last = MAXX ( TOPN ( 1, _Base, [@x], DESC ), [@v] )
        RETURN
            IF (
                COUNTROWS ( _Base ) < 2,
                BLANK (),
                "data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='120' height='32' viewBox='0 0 120 32'><polygon fill='"
                    & SUBSTITUTE ( pLineColor, "#", "%23" )
                    & "' fill-opacity='0.2' stroke='none' points='"
                    & MAXX ( TOPN ( 1, _Base, [@x], ASC ), FORMAT ( 3.5 + DIVIDE ( [@x] - _XMin, _XMax - _XMin, 0.5 ) * 113, "0.0", "en-US" ) )
                    & ","
                    & _Floor
                    & " "
                    & _Points
                    & " "
                    & MAXX ( TOPN ( 1, _Base, [@x], DESC ), FORMAT ( 3.5 + DIVIDE ( [@x] - _XMin, _XMax - _XMin, 0.5 ) * 113, "0.0", "en-US" ) )
                    & ","
                    & _Floor
                    & "'/><polyline fill='none' stroke='"
                    & SUBSTITUTE ( pLineColor, "#", "%23" )
                    & "' stroke-width='1.5' stroke-linejoin='round' stroke-linecap='round' points='"
                    & _Points
                    & "'/><circle cx='"
                    & MAXX ( TOPN ( 1, _Base, [@x], DESC ), FORMAT ( 3.5 + DIVIDE ( [@x] - _XMin, _XMax - _XMin, 0.5 ) * 113, "0.0", "en-US" ) )
                    & "' cy='"
                    & FORMAT ( 3.5 + ( 1 - DIVIDE ( _Last - _Lo, _Hi - _Lo, 0.5 ) ) * 25, "0.0", "en-US" )
                    & "' r='2.6' fill='"
                    & SUBSTITUTE ( pLineColor, "#", "%23" )
                    & "'/></svg>"
            )

EVALUATE { VizForge.SvgSparklineArea ( [Sales], 'Date'[Month Start] ) }

-- 2) Then create the measure and set Measure tools > Data category = Image URL:
-- Sparkline Area = VizForge.SvgSparklineArea ( [Sales], 'Date'[Month Start] )
--    Colours and thresholds are optional parameters: pass a value after the fields to override one.
--    Pass colours as plain "#RRGGBB"; the function encodes the # for the data URI.

Placing it in a report

Rows hold the category, the measure goes in Values, Image size 32 × 120. In a matrix, keep months off the columns: every cell would then draw a one-point area and return BLANK(). Remember the Image URL data category. All setup steps.

Gotchas

When an SVG measure isn't enough

A custom visual can add a reference line for the period average and point tooltips. See the KPI card custom visual for what an interactive version can do.

KPI card designs using it

Finished designs built on this pattern, from the KPI card gallery.