Join us at FabCon Atlanta from March 16 - 20, 2026, for the ultimate Fabric, Power BI, AI and SQL community-led event. Save $200 with code FABCOMM.
Register now!Learn from the best! Meet the four finalists headed to the FINALS of the Power BI Dataviz World Championships! Register now
Hello Experts,
I would like to build a Custom Visual using HTML, but I do not have enough experience in this area. I would appreciate your support with the following requirements:
Create a Waterfall chart based on the following data:
| 1 | Budget NPAT | 4,261,532 |
| 2 | Gross Margin | 2,733,696 |
| 3 | Variable Costs | -280,573 |
| 4 | 3rd Party Cost Recovery | -435,951 |
| 5 | Other Income | 32,571 |
| 6 | Fixed Costs | 1,324,187 |
| 7 | Support Cost | 738,378 |
| 8 | Depreciation | -664,124 |
| 9 | Bad Debt Provision | 799,823 |
| 10 | Finance Exp & Inc | -1,537,797 |
| 11 | Income Tax | -637,201 |
| 12 | Actual NPAT | 6,334,541 |
The data must be sorted by Index in ascending order.
Index 1 should appear on the far left of the chart.
Index 12 should appear on the far right of the chart.
Colors:
Index 1 (Budget NPAT) must be in color: #389BBD
Index 12 (Actual NPAT) must be in color: #A4D233
The columns between them:
Green for positive values
Red for negative values
Starting Point (Very Important):
Index 1 and Index 12 must start from zero on the Y-axis.
I have attached an example to show the required layout.
Note: The attached example is not working correctly. It is only for illustration of the expected design.
If possible, please provide a Power BI (.pbix) file for this example.
Thank you in advance for your support.
Solved! Go to Solution.
Hi @majid154a,
I thought I'd give you a hand to get started with this.
I've managed to get a component working in HTML:
Here is the HTML for it, you may test it in your browser and play around with the scale, prev-value, and curr-movement/curr-label variables. Notice positive values will turn green, negative will turn red.
<style>
:root {
--scale: 5455;
--prev-value: 5000;
--curr-movement: -1505;
--curr-label: "-1505";
--movement: calc(var(--curr-movement) / abs(var(--curr-movement)));
--multiplier: calc((var(--movement) + 1) / 2);
--color: calc(var(--multiplier) * 122);
--height: calc(abs(var(--curr-movement)) / var(--scale) * 100%);
--top: calc((var(--scale) - var(--prev-value)) / var(--scale) * 100% - (var(--multiplier) * var(--height)));
.p-outer {
text-align: center;
padding-top: 1.5em;
}
.p-area {
height: 90vh;
width: 90vw;
margin-left: auto;
margin-right: auto;
}
.p-block::after {
content: var(--curr-label);
top: -1.5em;
position: relative;
color: black;
}
.p-block {
height: var(--height);
background-color: hsl(var(--color),70%,50%);
top: var(--top);
width: 100%;
position: relative;
}
.category {
text-align: center;
color: hsl(0,0%,50%);
}
body {
font-family: sans-serif;
}
</style>
<div>
<div class="p-outer">
<div class="p-area">
<div class="p-block"></div>
</div>
<div class="category">Category name</div>
</div>
</div>
We can then turn this into a parameterised DAX measure:
HTML Waterfall Bar =
VAR Scale = [Scale] // Replace with your max absolute value or dynamic max scale measure
VAR PrevValue = [Previous Cumulative Value] // Your measure for the running total BEFORE this step
VAR CurrMovement = [Variance / Delta] // Your measure for this step's change (positive or negative)
VAR CategoryName = SELECTEDVALUE('Category'[Category Name]) // or whatever your category field is
VAR CurrLabel = FORMAT(CurrMovement, "#,##0") // or use FIXED/ROUND as preferred
RETURN
"<html>
<head>
<style>
:root {
--scale: " & Scale & ";
--prev-value: " & PrevValue & ";
--curr-movement: " & CurrMovement & ";
--curr-label: """ & CurrLabel & """;
--movement: calc(var(--curr-movement) / abs(var(--curr-movement)));
--multiplier: calc((var(--movement) + 1) / 2);
--color: calc(var(--multiplier) * 122);
--height: calc(abs(var(--curr-movement)) / var(--scale) * 100%);
--top: calc((var(--scale) - var(--prev-value)) / var(--scale) * 100% - (var(--multiplier) * var(--height)));
}
.p-outer {
text-align: center;
padding-top: 1.5em;
}
.p-area {
height: 90vh;
width: 90vw;
margin-left: auto;
margin-right: auto;
}
.p-block::after {
content: var(--curr-label);
top: -1.5em;
position: relative;
color: black;
}
.p-block {
height: var(--height);
background-color: hsl(var(--color),70%,50%);
top: var(--top);
width: 100%;
position: relative;
}
.category {
text-align: center;
color: hsl(0,0%,50%);
}
body {
font-family: sans-serif;
}
</style>
</head>
<body>
<div class='p-outer'>
<div class='p-area'>
<div class='p-block'></div>
</div>
<div class='category'>" & CategoryName & "</div>
</div>
</body>
</html>"
To get this working, you will need to create the following DAX measures:
You will also need to introduce logic for the Budget NPAT and Actual NPAT colors.
Granularity will need to be set to Category Name. Then sort by Category ID.
I hope this helps.
Hi @majid154a,
Thank you @Ashish_Mathur, for your insights.
With a sample dataset, I replicated your requirement in Power BI. On Page 1, I used the HTML Content visual to build the custom layout, and on Page 2, I utilized the standard Waterfall visual. I've attached the PBIX file for your review and included a Microsoft documentation link below for further details on the Waterfall visual.
Waterfall Charts in Power BI - Power BI | Microsoft Learn
Thank you.
Dear HTML Experts,
I need help for this question :
Waterfall by HTML Help - Microsoft Fabric Community
Hi @majid154a,
Could you review the solution that @TropicInsight @Ashish_Mathur and I provided above? Please let us know if it helped resolve the issue, or if you notice any gaps, we would be happy to address them.
Thank you.
Hi @majid154a,
Thank you @TropicInsight, for your insights,
Have you had a chance to review the solution we shared earlier? If the issue persists, feel free to reply so we can help further.
Thank you.
Hi @majid154a,
Thank you @Ashish_Mathur, for your insights.
With a sample dataset, I replicated your requirement in Power BI. On Page 1, I used the HTML Content visual to build the custom layout, and on Page 2, I utilized the standard Waterfall visual. I've attached the PBIX file for your review and included a Microsoft documentation link below for further details on the Waterfall visual.
Waterfall Charts in Power BI - Power BI | Microsoft Learn
Thank you.
Thank you,
itw worked.
Thank you again.
But how I can show data label, I tried in visual formate, I didnt fint option for that
Hi,
Why would you not want to use the built in waterfall chart visual?
Hi @majid154a,
I thought I'd give you a hand to get started with this.
I've managed to get a component working in HTML:
Here is the HTML for it, you may test it in your browser and play around with the scale, prev-value, and curr-movement/curr-label variables. Notice positive values will turn green, negative will turn red.
<style>
:root {
--scale: 5455;
--prev-value: 5000;
--curr-movement: -1505;
--curr-label: "-1505";
--movement: calc(var(--curr-movement) / abs(var(--curr-movement)));
--multiplier: calc((var(--movement) + 1) / 2);
--color: calc(var(--multiplier) * 122);
--height: calc(abs(var(--curr-movement)) / var(--scale) * 100%);
--top: calc((var(--scale) - var(--prev-value)) / var(--scale) * 100% - (var(--multiplier) * var(--height)));
.p-outer {
text-align: center;
padding-top: 1.5em;
}
.p-area {
height: 90vh;
width: 90vw;
margin-left: auto;
margin-right: auto;
}
.p-block::after {
content: var(--curr-label);
top: -1.5em;
position: relative;
color: black;
}
.p-block {
height: var(--height);
background-color: hsl(var(--color),70%,50%);
top: var(--top);
width: 100%;
position: relative;
}
.category {
text-align: center;
color: hsl(0,0%,50%);
}
body {
font-family: sans-serif;
}
</style>
<div>
<div class="p-outer">
<div class="p-area">
<div class="p-block"></div>
</div>
<div class="category">Category name</div>
</div>
</div>
We can then turn this into a parameterised DAX measure:
HTML Waterfall Bar =
VAR Scale = [Scale] // Replace with your max absolute value or dynamic max scale measure
VAR PrevValue = [Previous Cumulative Value] // Your measure for the running total BEFORE this step
VAR CurrMovement = [Variance / Delta] // Your measure for this step's change (positive or negative)
VAR CategoryName = SELECTEDVALUE('Category'[Category Name]) // or whatever your category field is
VAR CurrLabel = FORMAT(CurrMovement, "#,##0") // or use FIXED/ROUND as preferred
RETURN
"<html>
<head>
<style>
:root {
--scale: " & Scale & ";
--prev-value: " & PrevValue & ";
--curr-movement: " & CurrMovement & ";
--curr-label: """ & CurrLabel & """;
--movement: calc(var(--curr-movement) / abs(var(--curr-movement)));
--multiplier: calc((var(--movement) + 1) / 2);
--color: calc(var(--multiplier) * 122);
--height: calc(abs(var(--curr-movement)) / var(--scale) * 100%);
--top: calc((var(--scale) - var(--prev-value)) / var(--scale) * 100% - (var(--multiplier) * var(--height)));
}
.p-outer {
text-align: center;
padding-top: 1.5em;
}
.p-area {
height: 90vh;
width: 90vw;
margin-left: auto;
margin-right: auto;
}
.p-block::after {
content: var(--curr-label);
top: -1.5em;
position: relative;
color: black;
}
.p-block {
height: var(--height);
background-color: hsl(var(--color),70%,50%);
top: var(--top);
width: 100%;
position: relative;
}
.category {
text-align: center;
color: hsl(0,0%,50%);
}
body {
font-family: sans-serif;
}
</style>
</head>
<body>
<div class='p-outer'>
<div class='p-area'>
<div class='p-block'></div>
</div>
<div class='category'>" & CategoryName & "</div>
</div>
</body>
</html>"
To get this working, you will need to create the following DAX measures:
You will also need to introduce logic for the Budget NPAT and Actual NPAT colors.
Granularity will need to be set to Category Name. Then sort by Category ID.
I hope this helps.
Share feedback directly with Fabric product managers, participate in targeted research studies and influence the Fabric roadmap.
Check out the February 2026 Power BI update to learn about new features.
| User | Count |
|---|---|
| 67 | |
| 59 | |
| 45 | |
| 19 | |
| 15 |