Dynamic PowerBI Backgrounds

Dynamic PowerBI Backgrounds

If you saw a couple of my posts on LinkedIn you would have seen some of the things I have been doing to mess with SVGs, HTML, animation and in this initial case Pokémon. I wanted to build a way to be able to seamlessly transition from one colour background to another but in a smooth and animated way driven by slicers, and all linked to dax measures. So, this blog post will give you a quick and easy way to achieve Dynamic PowerBI Backgrounds,

Doing things this way means rather than relying on bookmarks, theme files to switch up colours or implement ideas such as dark mode we can instead add smooth transitions and make changes in a more dynamic way.

Use SVG, HTML & CSS to enhance PowerBI reports – Home

Firstly I configured the measure – this is currently linked to a simple table referencing the Background Type but this of course could be any of your values / data sets.

I have created two sets of colours relating to the selected option to show the two ends of the gradient. This means when we apply the animation we gain a subtle effect (of course you could just use a simple base colour).

To create a smoother transition between colours I have set all to initially show as a warm white colour, so instead of instantly performing a jarring switch, the screen goes light and slowly moves to the new selected colour. In my code I have also layered a slight vignette to the edges of the image to emphasise the display.

As part of this code it is also important to select the correct width and height to ensure the effect fills the screen (set the same as your PBI reports or at least the same aspect ratio such as 1920×1080 if using 16:9)

HTML_Dynamic_Back = 
VAR selectedOption =
    // Get the selected background option, defaulting to "Light" if none is selected
    SELECTEDVALUE(BackgroundType[BackgroundType], "Light")

VAR gradientStart =
    // Define gradient start colours for each option
    SWITCH(
        TRUE(),
        selectedOption = "Light", "#F2EFE9",  
        selectedOption = "Dark", "#1A1A1A",   
        selectedOption = "Middle", "#A8A8A8", 
        selectedOption = "Red", "#F08030",   
        selectedOption = "Green", "#78C850",  
        selectedOption = "Blue", "#6890F0",   
        selectedOption = "Yellow", "#F8D030", 
        selectedOption = "Orange", "#FFA500", 
        "#6BFAD8"                             
    )

VAR gradientEnd =
    // Define gradient end colours for a lighter variation of each option
    SWITCH(
        TRUE(),
        selectedOption = "Light", "#FFFFFF",  
        selectedOption = "Dark", "#575757",   
        selectedOption = "Middle", "#D8D8D8", 
        selectedOption = "Red", "#FFD6C1",    
        selectedOption = "Green", "#E6FFE6",  
        selectedOption = "Blue", "#E6F5FF", 
        selectedOption = "Yellow", "#FFFFE0", 
        selectedOption = "Orange", "#FFE6CC", 
        "#FFFFFF"                             
    )

VAR warmOffWhite = "#F2EFE9" // A warm off-white base colour

VAR svg =
    // Construct the SVG with animated gradients and vignette effect
    "<svg xmlns='http://www.w3.org/2000/svg' width='1920' height='1080' preserveAspectRatio='none'>" &
    "   <defs>" &
    "       <linearGradient id='bg-gradient' x1='0%' y1='0%' x2='100%' y2='100%'>" &
    "           <stop offset='0%' stop-color='" & warmOffWhite & "'>" &
    "               <animate attributeName='stop-color' values='" & warmOffWhite & ";" & gradientStart & "' dur='4s' begin='0s' fill='freeze' repeatCount='1'/>" &
    "               <animate attributeName='stop-color' values='" & gradientStart & ";" & gradientEnd & ";" & gradientStart & "' dur='6s' begin='4s' repeatCount='indefinite'/>" &
    "           </stop>" &
    "           <stop offset='100%' stop-color='" & warmOffWhite & "'>" &
    "               <animate attributeName='stop-color' values='" & warmOffWhite & ";" & gradientEnd & "' dur='4s' begin='0s' fill='freeze' repeatCount='1'/>" &
    "               <animate attributeName='stop-color' values='" & gradientEnd & ";" & gradientStart & ";" & gradientEnd & "' dur='6s' begin='4s' repeatCount='indefinite'/>" &
    "           </stop>" &
    "           <animate attributeName='x1' values='0%; -20%; 0%; 20%; 0%' dur='15s' repeatCount='indefinite'/>" &
    "           <animate attributeName='y1' values='0%; -20%; 0%; 20%; 0%' dur='15s' repeatCount='indefinite'/>" &
    "           <animate attributeName='x2' values='100%; 120%; 100%; 80%; 100%' dur='15s' repeatCount='indefinite'/>" &
    "           <animate attributeName='y2' values='100%; 120%; 100%; 80%; 100%' dur='15s' repeatCount='indefinite'/>" &
    "       </linearGradient>" &
    "       <radialGradient id='vignette-gradient' cx='50%' cy='50%' r='75%' fx='50%' fy='50%'>" &
    "           <stop offset='0%' stop-color='black' stop-opacity='0'/>" &
    "           <stop offset='60%' stop-color='black' stop-opacity='0'/>" &
    "           <stop offset='80%' stop-color='#575757' stop-opacity='0.02'/>" &
    "           <stop offset='100%' stop-color='#575757' stop-opacity='0.1'/>" &
    "       </radialGradient>" &
    "   </defs>" &
    "   <rect width='1920' height='1080' fill='url(#bg-gradient)'/>" &
    "   <rect width='1920' height='1080' fill='url(#vignette-gradient)'/>" &
    "</svg>"

RETURN
    "data:image/svg+xml;utf8," & svg

In this step we need to setup the card to be able to apply the measure. As with my other examples I have been using the new card visual.

Firstly, on the card, apply the measure under the image section.

  • Select Image URL
  • Select the measure
  • Add a column / value to the card to the Data parameter (any is fine we are going to remove this from view)

Next we need to resize the card to the full size of the window (or at least the area wanting to use) and then disable the values / labels under the Callout values section:

  • Disable Values
  • Disable Label

Now all padding needs to be removed from the card as well as removing all existing backgrounds / style effects

Under Visual / Cards:

  • Disable Background
  • Disable Border
  • Change Padding to custom and set all to 0px

Under Visual / Images

  • Change Space between Image and callout to 0px

Under General / Effects

  • Disable Background
  • Under General / Properties
  • Set all Padding to 0px

Now to test – I’ve added a slicer to switch between the different colours in my measure for example

To get the best effect from the dynamic background I have set a level of transparency to the visuals (if not dynamically changing these colours too)

Thanks for reading! Please have a play and let me know what cool things you make! Some actual use cases so far: enhancing UI / UX, a way to light mode / dark mode or accessibility options!