Articles in this section

ActivTrak for Power BI - HTML Content Visual

Renders any HTML your DAX returns as a live, styled visual — cards, KPI tiles, mini layouts, badges, whatever a measure can produce as an HTML string. Use it when a native Power BI visual can't quite get the layout, typography, or conditional styling you need, and you're comfortable authoring that styling in a DAX measure instead.

  • Turn a single DAX measure into a fully custom-styled card or tile
  • Iterate the same HTML template once per row with Group By, so one measure renders a whole grid of cards
  • Theme the visual from the format pane — colors flow into the HTML via CSS variables, so templates stay in sync with report theming without editing DAX
  • Click a rendered row to cross-filter the rest of the report, same as a native visual

Worth knowing

  • One HTML string per row. Without Group By, the visual renders a single block from the first (only) row the measure returns. Add Group By to get one clickable row per category value (e.g., one card per Team or User).
  • HTML is sanitized before it renders. The visual runs everything through DOMPurify. <script> tags, inline event handlers (onclick, etc.), and javascript: URIs are always stripped — this is not configurable. <style> blocks and external links are allowed only if the corresponding Advanced toggle is on (see below).
  • Theme colors are CSS variables, not just format-pane cosmetics. The eight Theme Colors map to --pbiv-* custom properties your HTML can reference directly (e.g. background:var(--pbiv-bg)). Set them once in the format pane and every measure that uses the variables stays in sync.
  • Debug Mode is a build-time tool, not an end-user setting. Turning it on replaces the rendered output with a diagnostic panel (current theme values, row count, raw HTML source, a quick-reference cheat sheet) — turn it off before sharing or publishing the report.
  • <img> tags work, but prefer base64 over external URLs. The sanitizer allows <img src="..."> with either an https:// URL or a base64 data: URI. However, since the manifest declares no privileges (privileges: [], see Limits), the visual has no explicit grant for outbound network calls — an externally-hosted image may render fine in Desktop but fail silently in the Service (or vice versa) depending on sandbox behavior. Embed images as base64 data: URIs when you need guaranteed rendering everywhere; treat https:// image URLs as untested until you've confirmed them in your actual target environment.

Contents

Fields

Field Role Required Notes
HTML Value Measure Yes A DAX measure that returns an HTML string. Evaluated once per row when Group By is present, once overall otherwise.
Group By Grouping (one or more columns) No The column(s) to iterate over — one row, and one clickable/selectable element, per distinct value. Multiple columns build a compound selection ID (e.g. Team + User).

If HTML Value is empty, the visual shows a placeholder prompting you to add a measure. If the measure returns no rows or empty strings, it shows "No HTML string returned by the measure."

Format pane

Layout

  • Padding (px) — inner padding applied around the rendered HTML. Default 0.
  • Transparent Background — when on (default), the visual's own background is transparent so it inherits the page/theme background; turn off to force a solid background.

Theme Colors

Eight color pickers, each exposed to your HTML as a CSS custom property you can use inside inline style attributes or <style> blocks:

Format pane label CSS variable Default Suggested use
Accent --pbiv-accent #0078d4 Brand color, links, highlights
Background --pbiv-bg #ffffff Card/tile background
Text --pbiv-text #0f172a Primary text
Text Muted --pbiv-text-muted #64748b Labels, captions, secondary text
Border --pbiv-border #e2e8f0 Dividers, card borders
Positive --pbiv-positive #16a34a Good / on-track indicators
Negative --pbiv-negative #dc2626 Bad / at-risk indicators
Warning --pbiv-warning #d97706 Caution indicators

Example:

<div style="background: var(--pbiv-bg); border: 1px solid var(--pbiv-border); border-radius: 6px; padding: 12px 16px;">
  <div style="font-size: 11px; color: var(--pbiv-text-muted);">Label</div>
  <div style="font-size: 24px; font-weight: 700; color: var(--pbiv-text);">Value</div>
</div>

High contrast mode: when Power BI's high-contrast theme is active, the visual overrides all eight variables to the OS-provided high-contrast colors regardless of the format pane settings, so accessibility isn't broken by a custom theme.

Advanced

  • Max Rows — caps how many Group By rows render. Default 1000; clamped between 1 and 30000 regardless of what's entered.
  • Debug Mode — off by default. See Debug Mode below.
  • Allow External Links — on by default. When on, <a target="_blank"> is permitted (the visual auto-adds rel="noopener noreferrer" for safety). When off, links can't open in a new tab.
  • Allow Style Blocks — on by default. When on, <style> tags inside the returned HTML are kept (after stripping @import and url() references, which are always blocked). When off, any <style> block is removed by the sanitizer.

Selection & cross-filtering

Only active when Group By is used (each row needs a selection ID to filter by):

  • Click a row to filter the rest of the report to that value; click it again to clear.
  • Ctrl/Cmd-click to multi-select several rows at once.
  • Click empty space in the visual to clear the current selection.
  • Right-click a row for the standard Power BI context menu (e.g. "Include"/"Exclude").
  • Keyboard: arrow keys / Home / End move focus between rows, Enter or Space selects the focused row, Escape clears selection. Full keyboard support means the visual meets standard accessibility expectations for interactive report elements.
  • When another visual's cross-filter or a highlight is applied, unselected/non-highlighted rows are visually dimmed rather than hidden, so the full set stays visible for context.

If Allow Interactions is disabled at the report level (e.g. inside a tooltip or a visual with interactions turned off), click/keyboard handling is skipped automatically.

Building your first HTML measure

My Card HTML =
VAR Value_ = [Your Measure]
VAR Label_ = "Label"
RETURN
"<div style="style;" solid="solid">
  <div style="font-size: 11px; color: var(--pbiv-text-muted);">" & Label_ & "</div>
  <div style="font-size: 24px; font-weight: 700; color: var(--pbiv-text);">" & Value_ & "</div>"
</div>"

Drop the measure into HTML Value. Add a column to Group By to repeat the same template once per category, driven by row context inside the measure.

Allowed: standard HTML tags (including <img>), inline CSS, <style> blocks (if enabled), https:// links, base64 data: image URIs.
Always blocked: <script>, inline event handlers (onclick, etc.), javascript: URIs, <iframe>.

Debug Mode

Turning on Advanced → Debug Mode replaces the visual's rendered output with a diagnostic panel showing:

  • Group By columns in use, row count, rows currently shown, whether highlights are active, and high-contrast mode status
  • The current resolved value of each --pbiv-* theme variable, with a color swatch
  • A live preview of row 0's rendered HTML plus its raw HTML source (first 800 characters, escaped)
  • An in-visual quick reference: field wells, the CSS variable table, sanitization rules, and the starter measure template above

Useful while authoring a new HTML measure; turn it back off before the report goes to end users, since it disables click/keyboard interaction and shows raw HTML source.

Troubleshooting

Symptom Likely cause
Visual shows a placeholder prompting for a measure HTML Value field is empty
"No HTML string returned by the measure." The measure evaluated to blank/empty for every row in scope
A <style> block you added has no effect Allow Style Blocks is off, or the block used @import/url(), which is always stripped
A link won't open in a new tab Allow External Links is off, or the anchor is missing target="_blank"
An image doesn't render The src is an external https:// URL and the sandbox blocked the network call — switch to a base64 data: URI (see Worth knowing)
Fewer rows than expected Max Rows (Advanced) is clamping the Group By output — max is 30,000 regardless of what's entered
Clicking a row does nothing No Group By column is set (selection requires a per-row ID), or Allow Interactions is disabled at the report level (e.g., inside a tooltip)

Limits

  • Max Rows is clamped to 30,000 even if a higher value is entered; the underlying data reduction on the Group By categories is also capped at 30,000 categories.
  • The visual renders one HTML string per Group By row — it does not aggregate or merge multiple measure results into one row.
  • Requires Power BI custom visual API 5.11.0 or later (set in the manifest); very old Desktop/Service versions may not load it.
  • No external network calls or custom privileges are declared (privileges: []) — the visual only renders HTML/CSS you provide via DAX; it doesn't fetch remote resources on its own.
Was this article helpful?
0 out of 0 found this helpful