Power BI KPI using HTML and CSS
Matthew Spuffard
Expert in Data, Analytics & Project Controls | BaseOne.uk | Helping businesses make better decisions!
HTML (Hypertext Markup Language) and CSS (Cascading Style Sheets) are powerful tools that can be used to enhance the visual appeal and functionality of Power BI reports. By utilizing these languages, you can create custom KPIs (Key Performance Indicators) and visuals that are tailored to the specific needs of your business or organization.
One of the key benefits of using HTML and CSS in Power BI is the ability to create more visually appealing and informative graphics. For example, you can use HTML and CSS to create custom charts and graphs that are designed to effectively communicate the data you are trying to present. Additionally, you can use these languages to create custom formatting options, such as color schemes, font styles, and background images, which can help to make your reports more engaging and easier to understand.
In this tutorial, you'll learn how to create this simple conditional KPI.
First off, here's my toolkit.
1. A KPI you can make in ten Minutes with HTML & CSS
1.1 - Basic HTML structure
Start by creating the basic structure of the HTML page by defining the head and body tags. In the head section, we will include the Google font link, which will be used for styling the KPI. The font I've chosen is Open Sans.
<html
<head>
<link rel="preconnect" >
<link rel="preconnect" crossorigin>
<link rel="stylesheet">
</head>
<body>
</body>
</html>>
1.2 - HTML KPI Elements
Next, we will create the container for the KPI. We will use a div element with a class of kpiBox. Inside the div, we will include the KPI name, value, and difference.
<div class="kpiBox"
<span class="kpiName" >HTML KPI</span>
<span class="kpi"> 35%</span>
<span class="kpiDifference">+3%</span>
</div>>
The kpiBox code should go in between the body tags of the HTML.
So, your HTML now looks like this.
<html
<head>
? <link rel="preconnect" >
? <link rel="preconnect" crossorigin>
? <link rel="stylesheet">
</head>
<body>
<div class="kpiBox">
? ? <span class="kpiName" >HTML KPI</span>
? ? <span class="kpi"> 35%</span>
? ? <span class="kpiDifference">+3%</span>
</div>
</body>
</html>>
OK, thats all the HTML we need.
Let's style it with CSS
1.3 - Styling the KPI box with CSS
Now, we will add the CSS styles for the KPI container. We will set the display to inline-block, width, and height to 10rem and 5rem, and background-color to #0E1218. We will also add a border-left of 10px and solid black color. We will also add padding-top and padding-left to add spacing between the elements inside the container.
.kpiBox {
? display: inline-block;
? width: 10rem;
? height: 5rem;
? background-color: #0E1218;
? border-left: 10px solid black;
? padding-top: 1rem;
? padding-left: 1.5rem;
? font-family: 'open sans';
}
1.4 - Style other KPI elements with CSS
Next, we'll style the KPI name, value, and difference. For the KPI name, we will set the display to block, font-size to 1.2rem and font-weight to 800. For the KPI value, we will set the font-size to 2rem. For the KPI difference, we will set the padding-left to 1rem, font-size to 1.3rem and color to grey.
.kpiName {
display: block;
font-size: 20px;
font-weight: 800;
}
.kpi {
font-size: 2rem;
}
.kpiDifference{
padding-left: 1rem;
font-size:1.3rem;
color: grey;
}
1.5 - Conditional Formatting with CSS animation
Lastly, we will add an animation to change the color of the border and create the conditional formatting. What this does, is create gradient transition animation from one colour to another, between the values of 0 and 100%.
@keyframes color-gradient
? ?0% {
? ? border-color: #d12421;
? }
? 50% {
? ? border-color: #ffb200;
? }
? 100% {
? ? border-color: #008979;
? }
}
1.6 - Adding the animation controls to the .kpibox
Then we will add some more CSS to the .kpibox to set the animation-fill-mode to forwards and animation-play-state to paused.
? animation: color-gradient 100s linear 1;
? animation-fill-mode: forwards;
? animation-play-state: paused;;
We don't want the animation to play, just to select a frame of the animation, and therefore a color within the gradient transition.
Your CSS in full looks like this.
.kpiBox
? display: inline-block;
? width: 10rem;
? height: 5rem;
? background-color: #0E1218;
? border-left: 10px solid black;
? padding-top: 1rem;
? padding-left: 1.5rem;
? font-family: 'open sans';
??
? animation: color-gradient 100s linear 1;
? animation-fill-mode: forwards;
? animation-play-state: paused;
}
.kpiName {
? display:block;
? font-size: 20px;
? font-weight: 800;
? color: white;
}
.kpi {
? font-size: 2rem;
? color: white;
}
.kpiDifference{
? padding-left: 1rem;
? font-size:1.3rem;
? color: grey;
}
@keyframes color-gradient {
? ?0% {
? ? border-color: #d12421;
? }
? 50% {
? ? border-color: #ffb200;
? }
? 100% {
? ? border-color: #008979;
? }
Here it all is in jsfiddle.
1.7 - Controlling the colour conditions
Next add the animation-delay control to your KPI HTML by editing the following line of code to look like this...
<div class="kpiBox" style="animation-delay: -100s;">
This uses the delay time in negative seconds to control the colour of the paused gradient animation. Cool huh?
2. Bringing the HTML & CSS together.
2.1 - Unless your visual allows seperate HTML and CSS measures (like the HTML Text Styler by BI Samauri) you'll need to embed the CSS into the HTML using the style tag.
To do this create a <style></style> tag within your body tags and paste the CSS between them.
So, it looks like this...
<!DOCTYPE html
<html>
<head>
? <link rel="preconnect" >
? <link rel="preconnect" crossorigin>
? <link rel="stylesheet">
</head>
<body>
<style>
.kpiBox{
? display: inline-block;
? width: 10rem;
? height: 5rem;
? background-color: #0E1218;
? border-left: 10px solid black;
? padding-top: 1rem;
? padding-left: 1.5rem;
? font-family: 'open sans';
??
? animation: color-gradient 100s linear 1;
? animation-fill-mode: forwards;
? animation-play-state: paused;
}
.kpiName {
? display:block;
? font-size: 20px;
? font-weight: 800;
? color: white;
}
.kpi {
? font-size: 2rem;
? color: white;
}
.kpiDifference{
? padding-left: 1rem;
? font-size:1.3rem;
? color: grey;
}
@keyframes color-gradient {
? ?0% {
? ? border-color: #d12421;
? }
? 50% {
? ? border-color: #ffb200;
? }
? 100% {
? ? border-color: #008979;
? }
}
</style>
<div class="kpiBox" style="animation-delay: -100s;">
? ? <span class="kpiName" >HTML KPI</span>
? ? <span class="kpi"> 35%</span>
? ? <span class="kpiDifference">+3%</span>
</div>
</body>
</html>>
Note how the CSS is in between the Style tags, and within the body of the HTML.
3 - Getting the code ready for Power BI
领英推荐
3.1 - Doubling the quotation marks
In Power BI, when writing DAX, we already use single quotation marks ". We also use them in HTML, and this causes conflicts.
So, to get around this, we need to double quote them.
I use Visual Studio code to do this, but you could use word, or any other text editor.
I'll simply paste in the code, and find/replace single marks, with double marks.
While I'm there I'll right click and format the code as well.
Now the HTML parts of your code should have double quotation marks instead of single.
After formatting, the whole script looks like this in VSCode.
Note how the Visual Studio Code has highlighted the double quotes as errors! Don't worry, this is fine. They're not errors in our Power BI measures.
Step 3 - Creating the visual in Power BI
3.1 - Setting up Power BI
I've created a simple dataset for this visual, using the CSS classes as the column headers to keep things simple. But you can create measures to include any data you like. Make sure you've downloaded your HTML visual form app.source as well.
3.2 - Creating the HTML Measure
Create a new measure, I've called mine HTML. Then create some variables using the VAR statement to define the values we will insert to the KPI.
HTML =
VAR KPI_Name = SELECTEDVALUE('HTMLTable'[KPI Name])
VAR KPI_Value = FORMAT(SELECTEDVALUE('HTMLTable'[KPI]),"0.0%")
VAR KPI_Difference = FORMAT(SELECTEDVALUE(HTMLTable[KPI Difference]),"0%")
VAR KPI_Cond = SELECTEDVALUE('HTMLTable'[KPI])*100 *-1
RETURN
"
"
This is what the measures are doing.
3.3 - Adding the HTML/CSS
Between the quotes that are open, I will paste the entire HTML and CSS script.
HTML =
VAR KPI_Name = SELECTEDVALUE('HTMLTable'[KPI Name])
VAR KPI_Value = FORMAT(SELECTEDVALUE('HTMLTable'[KPI]),"0.0%")
VAR KPI_Difference = FORMAT(SELECTEDVALUE(HTMLTable[KPI Difference]),"0%")
VAR KPI_Cond = SELECTEDVALUE('HTMLTable'[KPI])*100 *-1
RETURN
"
<!DOCTYPE html>
<html>
<head>
? <link rel=""preconnect"" href=""https://fonts.googleapis.com"">
? <link rel=""preconnect"" href=""https://fonts.gstatic.com"" crossorigin>
? <link href=""https://fonts.googleapis.com/css2?family=Open+Sans&display=swap"" rel=""stylesheet"">
</head>
<body>
<style>
.kpiBox{
? display: inline-block;
? width: 10rem;
? height: 5rem;
? background-color: #0E1218;
? border-left: 10px solid white;
? padding-top: 1rem;
? padding-left: 1.5rem;
? font-family: 'open sans';
?
? animation: color-gradient 100s linear 1;
? animation-fill-mode: forwards;
? animation-play-state: paused;
}
.kpiName {
? display:block;
? font-size: 20px;
? font-weight: 800;
? color: white;
}
.kpi {
? font-size: 2rem;
? color: white;
}
.kpiDifference{
? padding-left: 1rem;
? font-size:1.3rem;
? color: grey;
}
@keyframes color-gradient {
? ?0% {
? ? border-color: red;
? }
? 50% {
? ? border-color: yellow;
? }
? 100% {
? ? border-color: green;
? }
}
</style>
<div class=""kpiBox"" style=""animation-delay: -50;"">
? ? <span class=""kpiName"" >HTML KPI</span>
? ? <span class=""kpi""> 35%</span>
? ? <span class=""kpiDifference"">+3%</span>
</div>
</body>
</html>
"
Then add the new measure to the visual.
3.4 - Plugging in the variables.
To add in the variable to the HTML, we need to put them between quotations and ampersands - "& &".
Remember we have four variables to add
But if you notice the kpibox - animation-delay is a negative whole number. So we'll need to convert our percentage to the same.
Now the HTML for the KPI box looks like this.
<div class=""kpiBox"" style=""animation-delay: "& KPI_Cond&"s;"">
? ? <span class=""kpiName"" >"&KPI_Name&"</span>
? ? <span class=""kpi"">"&KPI_Value&"</span>
? ? <span class=""kpiDifference"">"&KPI_Difference&"</span>
</div>
4. Final code, and testing
Here is the final code for the measure in Power BI.
HTML =
VAR KPI_Name = SELECTEDVALUE('HTMLTable'[KPI Name])
VAR KPI_Value = FORMAT(SELECTEDVALUE('HTMLTable'[KPI]),"0.0%")
VAR KPI_Difference = FORMAT(SELECTEDVALUE(HTMLTable[KPI Difference]),"0%")
VAR KPI_Cond = SELECTEDVALUE('HTMLTable'[KPI])*100 *-1
RETURN
"
<!DOCTYPE html>
<html>
<head>
? <link rel=""preconnect"" href=""https://fonts.googleapis.com"">
? <link rel=""preconnect"" href=""https://fonts.gstatic.com"" crossorigin>
? <link href=""https://fonts.googleapis.com/css2?family=Open+Sans&display=swap"" rel=""stylesheet"">
</head>
<body>
<style>
.kpiBox{
? display: inline-block;
? width: 10rem;
? height: 5rem;
? background-color: #0E1218;
? border-left: 10px solid white;
? padding-top: 1rem;
? padding-left: 1.5rem;
? font-family: 'open sans';
?
? animation: color-gradient 100s linear 1;
? animation-fill-mode: forwards;
? animation-play-state: paused;
}
.kpiName {
? display:block;
? font-size: 20px;
? font-weight: 800;
? color: white;
}
.kpi {
? font-size: 2rem;
? color: white;
}
.kpiDifference{
? padding-left: 1rem;
? font-size:1.3rem;
? color: grey;
}
@keyframes color-gradient {
? ?0% {
? ? border-color: red;
? }
? 50% {
? ? border-color: yellow;
? }
? 100% {
? ? border-color: green;
? }
}
</style>
<div class=""kpiBox"" style=""animation-delay: "&KPI_Cond&"s;"">
? ? <span class=""kpiName"" >"&KPI_Name&"</span>
? ? <span class=""kpi"">"&KPI_Value&"</span>
? ? <span class=""kpiDifference"">"&KPI_Difference&"</span>
</div>
</body>
</html>
"
To test this, I swapped the percentage to a parameter. Here's the result.
4.1 - More KPIs?
If you want more KPIs in the same row, you can copy and paste the kpiBox HTML, making sure you keep it inside the div tags. Make sure you set up more VARs, and plug them into additional KPIs.
The CSS class we mentioned in the first sections (display: inline-block;) forces the KPI to stack horizontally, if you want it vertically, then remove this. Then use padding for more white space between them
4.2 - More colours?
If you want more colours, simply change the CSS keyframes to suit. You can have as many as you want.
ADD MORE VALUES HERE FOR ADDIONAL CONDITIONS
@keyframes color-gradient {
? ?0% {
? ? border-color: red;
? }
? 50% {
? ? border-color: yellow;
? }
? 100% {
? ? border-color: green;
? }
}
And thats it.
This tutorial will be available on the BaseOne website in the next few days, complete with downloads.
Follow me :)
If you want more content like this, follow me, and this newsletter.
Senior Full Stack Developer with 11 years of experience | Team leader | React.js | Angular | D3.js | Plotly.js | Charticulator & Plotly.js visuals | C#
4 个月I would like to suggest my HTML/SVG/Handlebars Visual, it brings the same functionality, but you don't need to store HTML/SVG template in DAX queries.
Data Analyst || Motion Graphic Designer
1 年Thank you Matthew Spuffard ??
Senior Power BI Engineer @ FSP | Designing World Class Power BI Reports for Clients | Blogger at Not Just a Pretty Dashboard
1 年This is brilliant! Well explained, keep up the great work Matthew ??
Helping companies make customers happy ?? | Google and Microsoft Certified Data Analyst ??| Software Developer ?? | Lifelong Learner ??
1 年the correct website is jsfiddle.net, right? not .com
Analista | Data Analytics | Ti | Desenvolvimento
1 年Thank you for sharing . The information provided was valuable and well-explained. ????????