Tutorials/Power Apps/Build a Profile Picture Component with Initials Fallback in Power Apps
Power Appsintermediate

Build a Profile Picture Component with Initials Fallback in Power Apps

A step-by-step guide to creating a custom avatar control that fetches a user photo from Microsoft Entra ID and gracefully shows initials when none exists.

NA
Narmer Abader
@narmer · Published June 3, 2026

User avatars add a personal touch to any app and help team members quickly identify who is responsible for a task. In many organisations only a portion of users have a profile photo stored in Microsoft Entra ID (formerly Azure AD). When a photo is not available, you can still provide a clear visual identifier by showing the person’s initials inside a coloured circle – a pattern made popular by Office 365.

In this article you will learn how to build a custom avatar component for Power Apps that:

  • Displays the user’s profile photo when one exists.
  • Falls back to a circular badge with the person’s initials if no photo is available.
  • Assigns a consistent, unique background colour to each user.

Scenario Overview

Imagine you are building a task dashboard for a marketing agency called Campaign Tracker. Every task card must show the owner’s picture or initials so that team members can see at a glance who is working on what. Only about half of the employees have uploaded a photo to Entra ID, so you need a graceful fallback for the rest.

Setting Up the Data Source

Create a SharePoint list named CampaignTasks with the following columns:

Column NameType
TitleSingle line of text
OwnerPerson
DeadlineDate and Time

Populate the list with sample records. For example:

TitleOwnerDeadline
Launch email campaignElena Martinez2026-07-15
Design landing pageJames O’Brien2026-07-18
Write blog postPriya Sharma2026-07-20
Record video adMarcus Chen2026-07-22
Prepare social assetsFatima Al-Rashid2026-07-25

Open Power Apps Studio and create a new mobile app from blank. Add the CampaignTasks list as a data source. Insert a blank gallery and set its Items property to:

powerfxItems property of gallery
CampaignTasks

Add two labels to the gallery to show the task title and the owner’s display name.

ControlPropertyValue
Label (Title)TextThisItem.Title
Label (Owner)TextThisItem.Owner.DisplayName

Adding a Photo Column with Office365Users

To fetch user photos you need the Office365Users connector. Add it to your app from the Data pane.

Next, extend the gallery’s Items property to include a calculated photo column. The Office365Users.UserPhotoMetadata action checks whether a photo exists before attempting to download it, preventing runtime errors.

powerfxAdding a UserPhoto column
AddColumns(
  CampaignTasks,
  "UserPhoto",
  If(
      !IsBlank(Owner.Email) &&
      Office365Users.UserPhotoMetadata(Owner.Email).HasPhoto,
      Office365Users.UserPhotoV2(Owner.Email)
  )
)

Displaying the Profile Photo

Insert an Image control inside the gallery. Set its properties to make it a perfect circle:

PropertyValue
Width60
Height60
RadiusX60
RadiusY60

Bind the image to the photo column we just created:

powerfxImage property of the photo control
ThisItem.UserPhoto

Users who have a profile picture will now see it; others will see a blank square because ThisItem.UserPhoto is blank.

Creating the Initials Fallback

When no photo exists we want to show the user’s initials instead. Insert a Label control (not a button) and position it exactly over the image control (set X and Y to the image’s X and Y). Configure these properties:

PropertyValue
Width60
Height60
RadiusX60
RadiusY60
TextAlignmentTextAlignment.Center
DisplayModeDisplayMode.View
VisibleIsBlank(ThisItem.UserPhoto)
ColorColor.White
FontWeightFontWeight.Bold
FontSize20

Now we need to populate the label’s Text property with the user’s initials. The best way is to compute the initials in the gallery’s Items property by calling Office365Users.UserProfileV2 for each owner. Because nesting multiple AddColumns can make the formula long, you can build a single expression that adds both the photo and initials columns:

powerfxGallery Items with initials
AddColumns(
  AddColumns(
      CampaignTasks,
      "UserPhoto",
      If(
          !IsBlank(Owner.Email) &&
          Office365Users.UserPhotoMetadata(Owner.Email).HasPhoto,
          Office365Users.UserPhotoV2(Owner.Email)
      )
  ),
  "Initials",
  With(
      {
          userProfile: If(
              !IsBlank(Owner.Email),
              Office365Users.UserProfileV2(Owner.Email)
          )
      },
      Upper(
          Concatenate(
              Left(userProfile.givenName, 1),
              Left(userProfile.surname, 1)
          )
      )
  )
)

Finally, set the initials label’s Text property to:

powerfxInitials label Text property
ThisItem.Initials

Users without a photo will now see their two-letter initials centered in a white, round label.

Assigning a Unique Background Colour

To make each person easy to distinguish, we assign a consistent background colour to the initials label based on the person’s name. The colour palette is taken from Fluent UI’s persona colour set.

Use this expression in the Fill property of the initials label:

powerfxFill property for dynamic colour
With(
  {
      alphabetTable: ForAll(
          Sequence(26),
          {
              Letter: Char(64 + Value),
              Value: Value
          }
      ),
      colorPalette: Table(
          { Color: "#d13438", ID: 1 },   // Red 10
          { Color: "#ca5010", ID: 2 },   // Orange 20
          { Color: "#fce100", ID: 3 },   // Yellow 10
          { Color: "#0b6a0b", ID: 4 },   // Green 20
          { Color: "#00ad56", ID: 5 },   // Green Cyan 10
          { Color: "#00b7c3", ID: 6 },   // Cyan 10
          { Color: "#0078d4", ID: 7 },   // Cyan Blue 20
          { Color: "#5c2e91", ID: 8 },   // Blue Magenta 30
          { Color: "#881798", ID: 9 },   // Magenta 20
          { Color: "#e3008c", ID: 10 },  // Magenta Pink 10
          { Color: "#69797e", ID: 11 }   // Gray 20
      )
  },
  LookUp(
      colorPalette,
      ID = Mod(
          Sum(
              AddColumns(
                  Split(
                      Substitute(
                          Upper(ThisItem.Owner.DisplayName),
                          " ",
                          ""
                      ),
                      ""
                  ),
                  "MappedValue",
                  LookUp(
                      alphabetTable,
                      Letter = Result,
                      Value
                  )
              ),
              MappedValue
          ),
          11
      ) + 1,
      ColorValue(Color)
  )
)

Optimising Performance and Security

  • Delegation – The Office365Users.* functions do not delegate. If your CampaignTasks list contains thousands of rows, the gallery will fetch all records client-side before evaluating the user lookups. Consider filtering the gallery to a manageable set (e.g., tasks belonging to the current user only) or pre-caching user profiles in a collection.
  • Caching tactic – Load all unique owners’ profiles into a collection once (for example on app start) and then reference that collection inside the gallery. This reduces repeated calls to the connector.
  • Permissions – The Office365Users connector requires the signed-in user to have appropriate Entra ID permissions. Typically the User.Read.All or Directory.Read.All scope is needed to read other people’s profiles. If you’re building a Canvas app for your own tenant, these are usually granted by default, but in a production app verify that your users have the right permissions.
  • Error handling – Always guard Office365Users.UserPhotoV2 with a metadata check. An absent photo will throw a runtime error if you call it directly.

Common Pitfalls and Troubleshooting

  • Blank Owner email – If the person column is empty, Owner.Email is blank and the metadata call will fail. Always include an !IsBlank check (as shown in the formulas above).
  • Missing givenName or surname – Some user directory entries may not have these fields populated. In that case Left(userProfile.givenName,1) returns an empty string. You can extend the logic to fall back to the username or a default placeholder such as “?”.
  • Colour gaps – The palette above has 11 colours. If you have more than 11 users without photos, some colours will repeat. You can increase the palette size or use a hash-based approach to distribute colours more evenly.
  • Performance – Using Office365Users.UserProfileV2 inside AddColumns triggers one API call per unique owner in the gallery. This can be slow for galleries with many items. Pre-caching profiles in a collection as suggested earlier is the recommended mitigation.
  • Separator visibility – If you add a grey rectangle between gallery items, make sure its ZIndex is lower than the initials label so it doesn’t overlap the avatar.

Final Thoughts

By combining the Office365Users connector with a small amount of inline logic, you can create a polished avatar component that works for every user in your organisation – with or without a photo. The same technique can be reused across apps: wrap the gallery or a custom component once and drop it wherever you need a person’s face.

For a production app, consider moving the colour assignment formula into a component property or a separate collection so it’s easier to maintain.

References