• Design & Digital
  • Digital

How to create a KPI for Power BI using HTML and CSS

By Matthew Spuffard - 2023 Jan 24 12 mins read

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.

No alt text provided for this image

First off, here’s my toolkit.

  1. jsfiddle.net – This is a code playground, where I can easily write code and see the result. I’ll create the entire KPI in here first.
  2. Microsoft Visual Studio Code – by far the best code editor, I’ll use this to format and tweak the code.
  3. Power BI – the final step will be to take the formatted code and create some variables in Power Bi to populate the KPI with data.

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" 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>

</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" 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>

<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" 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 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.

No alt text provided for this image

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.

No alt text provided for this image

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.

  1. KPI_Name – returns the KPI Title
  2. KPI_Value – returns the main value as a percentage
  3. KPI_Difference – returns the smaller value
  4. KPI_Cond – returns the main KPI value as a whole negative number, so that it can be used in the animation to dictate what frame should be used to colour the left border. To do this, simply take the KPI percentage, multiply it by 100, and then multiply the result by negative 1. Easy.

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.

No alt text provided for this image

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

  1. KPI Title
  2. KPI Value
  3. KPI Difference
  4. KPI Conditional

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. Power BI using HTML and CSS – 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.

No alt text provided for this image

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 for more

Share:

Latest posts

  • Data
  • Data Management
2023 Dec 14 3 mins read
  • Data
  • Data Management
2023 Dec 7 2 mins read

Featured posts

Tags

  • CSS
  • HTML
  • power bi

Latest insights.

  • Data
  • Data Management
2023 Dec 14 3 mins read

Explore the transformative data analytics trends of 2023 that are reshaping businesses. Discover how augmented analytics, AI, real-time data, and more can drive your organization's success.

  • Data
  • Data Management
2023 Dec 7 2 mins read

Discover how Power BI's visualization tools can transform predictive analytics into actionable insights. Learn about interactive dashboards, custom visuals, and real-time data visualization in Power BI.

Our site uses cookies to distinguish you from other users of our site. This allows us to provide convenient viewing of our site, and also allows us to improve it. In order to continue working with the site, you need to accept the terms. Cookies policy

No thanks
Accept cookies