Add a Header Image to a Modern Page

We’re always trying to experiment with what’s possible with branding SharePoint. As one of the developers on the PixelMill team, I knew it was long overdue to try my hand at playing with the relatively new custom header and footer available in modern pages through custom SharePoint Framework (SPFx) Extensions. I decided to see if I could mimic a branded header bar by adding a logo into the header that would link back to the home page.


If you’re brand new to SPFx as I was, you’ll definitely want to head over to the good folks at Microsoft, who have lots of guided tutorials and videos to get you started. At the very least, you should:

Let’s do this!

At this point, your extension makes use of the Top and Bottom placeholders in modern pages to inject HTML. The header and footer content are defined by the properties passed to the query string parameters:

customActions={%22459e9d09-3ced-4486-8f80-6c2c92cc49b6%22:{%22location%22:%22ClientSideExtension.ApplicationCustomizer%22,%22properties%22:{%22Top%22:%22Top%20area%20of%20the%20page%22, %22Bottom%22:%22Bottom%20area%20in%20the%20page%22}}}

Custom header and footer - initial state

Those properties would be a pretty handy way to pass in an image URL so that you wouldn’t have to hard-code the image URL into the injected code. So that’s exactly what we’ll do!

In the rest of this tutorial, we will:

  • Add the image to the site assets,
  • Modify the code to pass in the image URL, and
  • Modify the rendered HTML code and CSS to display the image and link to the home page

First, upload the image you’d like to use into the Documents > Site Assets folder of your site (or really, any other location where you’d like to keep your image). Make a note of the image location URL.

Image added to Site Assets folder

Fire up your code editor to modify your previously-created HelloWorld extension.

Open src/extensions/helloWorld/HelloWorldApplicationCustomizer.ts. Look for the section where you define the IHelloWorldApplicationCustomizerProperties.

Properties object

Add a new line for the Logo:

export interface IHelloWorldApplicationCustomizerProperties {
Top: string;
Bottom: string;
Logo: string;

Now look for the section where the top placeholder is set:

Code where top placeholder is set

In the code below, I’ve added a logoString variable to hold the Logo property, then modified the HTML to add a link to the site home page, the image itself, and the original top text standing in for the image ALT attribute.

if ( {
let topString: string =;
if (!topString) {
topString = '(Top property was not defined.)';

let logoString: string =;
if (!logoString) {
console.error('Logo URL was not defined.');

if (this._topPlaceholder.domElement) {
this._topPlaceholder.domElement.innerHTML = `
<div class="${}">
<div class="ms-bgColor-themeDark ms-fontColor-white ${}">
<div class="${styles.logo}"><a href="${this.context.pageContext.web.absoluteUrl}"><img src="${escape(logoString)}" alt="${escape(topString)}" /></a></div>

Now open AppCustomizer.module.scss. Modify this with additional styles to format the image and top bar. I added some padding, removed the height of the top bar, and kept the logo to be 80px or less.

.app {
.top {
display: flex;
align-items: center;
justify-content: center;
padding: 10px;

.logo {
max-width: 80px;

max-width: 100%;
height: auto;

.bottom {
display: flex;
align-items: center;
justify-content: center;

Finally, open /sharepoint/assets/elements.xml and modify the ClientSideComponentProperties to add in the Logo property:

ClientSideComponentProperties="{"Top":"Alt text for image","Bottom":"Bottom area in the page","Logo":""}"&gt;

How it looks

If you don’t already have gulp running, go ahead and run gulp serve –nobrowser.

Then, open up a modern page and append this to the URL (don’t forget to replace the application ID with your own from the HelloWorldApplicationCustomizer.manifest.json and to link in your own logo image location):


Click “Load debug scripts” to allow the script to run locally.

Load scripts

And you’ll see your image, linking to the home page, in the top header!

The image shows up!

Now what?

You might be wondering how this would all deploy to SharePoint. I would suggest that you continue with the tutorials at Microsoft, starting from Deploy your Extension to SharePoint. One thing you’ll notice, though, is that there is no current interface for setting those Extension properties — you just install the solution as-is. What if you want to change the image location for some sites?

That’s where this handy PnP-Powershell command comes in: Add-PnPCustomAction. You can try doing something like this while connected to your SharePoint site in Powershell:

Add-PnPCustomAction -Name "HelloWorldCustomAction" -Title "HelloWorld" -Location "ClientSideExtension.ApplicationCustomizer" -ClientSideComponentId "459e9d09-3ced-4486-8f80-6c2c92cc49b6" -ClientSideComponentProperties "{"Top":"Alt%20text%20for%20image","Bottom":"Bottom%20area%20in%20the%20page","Logo":""}}"

Use with caution!

Unfortunately, it looks like my pretty image logo and visions of a fully branded and functional header are going to need to go back to the drawing board. While I’ve demonstrated that it’s possible to add some branding to the top of a Modern site, doing so effectively reduces the usable, scrollable section of the page. This becomes especially evident on a document library page:

Document Library with custom header and footer

While having the Top and Bottom placeholders are exciting, it will definitely take some good UX + UI work to make best use of the limited space. Our designers are already dreaming of some different things to try for upcoming Modern projects! If you’ve been coming up with some creative uses for the Top and Bottom placeholders, we’d love to hear about it in the comments below!

Corrie Haffly Corrie Haffly
Senior Web Developer
Sea Otter Enthusiast
Your SharePoint Tour Guide

2 thoughts on “Add a Header Image to a Modern Page

  1. Hi Corrie!
    Thank you for this.
    You are obviously the only one in the whole world, giving an example on this right now. But I can’t get it to work…
    What about the “&gt” character ending the ClientSideComponentProperties string, should it not be “>” as there is no corresponding “&lt” to it but a “<".
    I also had to replace the escape character for ampersand with just "&" in the loadSPFX link to get the script recognized at all by my browser.
    (Of this I am sure).
    Moreover, what about the "/:i:/r/" in the Logo path? I do not have this in my path, should it be there for a reason?
    I have tested changing all these things back an forth…still not working, always:
    Error: Script error for "https://localhost:4321/temp/manifests.js&quot;
    Hope you can sort out some things…

  2. Hi again
    Actually it is all working, after I reverted back to the original “starting point” project
    and did all this once again. Only thing needed for me was replacing the ampersand escape character (“&”) with just “&” (in the ?loadSPFX string), otherwise all paths or so was just as-is.
    However, when deploying, it was picky about the ClientSideComponentProperties string, where I had to replace all “”” with
    its escape character “"”.

Leave a Reply

Your email address will not be published. Required fields are marked *

Human Check *

Filed Under


Join us for a webinar with @PowellSoftware on September 5th at 9am PST as we discuss how you can transform your ‘online office’ as well as detailing 5 of the most requested features of any digital workspace.

Register now:

1 hour away from our July episode! Have you registered yet? If we tell you @ShrPntKnight and @MchlScttWlls are doing a two-man version of Jurassic Park, will that entice you? This session is sure to be DINO-mite! – #PixelMillWebinars

It’s the day of the show y’all! Join us at 11am PST for a look into #MicrosoftStream with @ShrPntKnight. See you in a couple hours! – #PixelMillWebinars

This is your 24-hour warning! Join the party tomorrow at 11am PST! – #PixelMillWebinars

We’re just 2 days away from our July session! Have you registered yet? We’ve got Microsoft things. We’ve got @ShrPntKnight things. We may even probably not have live musical performance things. What are you waiting for?! – #PixelMillWebinars