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.

Prereqs

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:
/sites/TeamSite?loadSPFX=true&debugManifestsFile=
https://localhost:4321/temp/manifests.js&
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:

1
2
3
4
5
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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
if (this.properties) {
let topString: string = this.properties.Top;
if (!topString) {
topString = '(Top property was not defined.)';
}
let logoString: string = this.properties.Logo;
if (!logoString) {
console.error('Logo URL was not defined.');
}
if (this._topPlaceholder.domElement) {
this._topPlaceholder.domElement.innerHTML = `
<div class="${styles.app}">
<div class="ms-bgColor-themeDark ms-fontColor-white ${styles.top}">
<div class="${styles.logo}"><a href="${this.context.pageContext.web.absoluteUrl}"><img src="${escape(logoString)}" alt="${escape(topString)}" /></a></div>
</div>
</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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
.app {
.top {
text-align:center;
line-height:2.5;
font-weight:bold;
display: flex;
align-items: center;
justify-content: center;
padding: 10px;
.logo {
max-width: 80px;
IMG {
max-width: 100%;
height: auto;
}
}
}
.bottom {
height:40px;
text-align:center;
line-height:2.5;
font-weight:bold;
display: flex;
align-items: center;
justify-content: center;
}
}

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

1
ClientSideComponentProperties="{"Top":"Alt text for image","Bottom":"Bottom area in the page","Logo":"https://yourtenant.sharepoint.com/:i:/r/sites/TeamSite/SiteAssets/icon.png"}"&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):

1
?loadSPFX=true&amp;debugManifestsFile=https://localhost:4321/temp/manifests.js&amp;customActions={"459e9d09-3ced-4486-8f80-6c2c92cc49b6":{"location":"ClientSideExtension.ApplicationCustomizer","properties":{"Top":"Alt%20text%20for%20image","Bottom":"Bottom%20area%20in%20the%20page","Logo":"https://yourtenant.sharepoint.com/:i:/r/sites/TeamSite/SiteAssets/icon.png"}}}

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:

1
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":"https://yourtenant.sharepoint.com/:i:/r/sites/TeamSite/SiteAssets/icon.png"}}"

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. PerryJ March 14, 2018

    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; http://requirejs.org/docs/errors.html#scripterror
    Hope you can sort out some things…

  2. PerryJ March 21, 2018

    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 Comment

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

Enter Code *

Filed Under

Related

2020 will soon be behind us (phew!), & now is the time to start planning to make the most of your 2021 #Intranet & #Digitalworkspace. We're offering two new workshops to help you plan for #digitaltransformation no matter where you are in your journey. http://ow.ly/sjEw50BZ0os

We're a little more than a week away from the next episode of the #PixelMillWebinars! Have you registered yet? This is a chance to strengthen and streamline your #digitalworkspace. http://ow.ly/RkWl50BYXrW

One of your employees’ most significant challenges lies in determining what tool is right for the task. One of our partners, @OrchestrySoft, joins the next episode of the #PixelMillWebinars to show how you can help your team overcome this obstacle. http://ow.ly/db7350BUFMG

We don't know about you, but we're feeling 22! Here's to our talented team and amazing clients who have been with us along our 22-year journey with many more exciting adventures to come.

Subscribe to PixelMill's
E-news

* indicates required

Let's Talk Digital
Workspaces Today

Get In Touch