A while ago, I wrote an article describing how you can inject a custom CSS stylesheet on SharePoint modern pages using an SPFx application extension. The code sample is now part of the SharePoint SP-Dev-Fx-Extensions repository on GitHub.

Since the article, I have been getting tons of e-mails asking all sorts of questions about the solution.

Since SPFx 1.6 was released, I took the opportunity to upgrade the solution to the latest and greatest version of the toolset. You can find the latest code on GitHub, or download the latest SharePoint package.

In this post, I'll (hopefully) answer some questions about how to use it.

Be smart!

You should really use the out-of-the-box customizations features before you resort to injecting custom CSS.

There are a few reasons why you shouldn't inject your own CSS:

  • Microsoft can change the HTML layout, element ids, or CSS classes at any time -- thus breaking your custom CSS.
  • Your customizations may hide or otherwise disable (or interfere with) new features Microsoft may introduce in the future.
  • Your customizations will be unsupported by Microsoft. Don't try to open support tickets (unless you're willing to pay for them, I guess).
  • Although the solution uses SPFx application extensions, the SharePoint/SPFx team will not be able to support your customizations.

That being said, there are valid reasons why you may need to inject custom CSS. Vesa and his team had to give careful consideration before accepting my solution as a code sample.

Here are some sample valid reasons for injecting your own CSS:

  • To meet your corporate branding guidelines (but consider using a custom theme first).
  • To solve unique accessibility requirements (such as importing a custom font to help with cognitive disabilities, such as dyslexia).
  • To solve an showstopping issue (you know, to shut up one of those bosses/clients that say distasteful stuff like: "we'll only use SharePoint Online/Office 365 **if** Microsoft fixes the ugly look and feel and [insert bad idea here]".
  • For limited-time customizations (like fixing an issue while you're waiting for Microsoft to fix it, or making it snow on Christmas Eve).

Ok, maybe the last one isn't such a valid reason.

Steps to inject your own CSS

  1. Download the code and build the solution, or download the pre-built solution.
  2. Go to your tenant's app catalog (usually at https://[yourtenant]
  3. Drag and drop the sppkg file from step 1 onto the library (or click Upload and select the file).
  4. When it prompts you Do you trust react-application-injectcss-client-side-solution? select Deploy (provided, of course, that you trust the solution!). If you want the extension to be available on all sites. check Make this solution available to all sites in the organization before you select Deploy. You may have to check-in the file if it is checked-out.
  5. It may take a while for the application extension to show up (I once had to wait overnight for the magical SharePoint elves to deploy the extension).
  6. Meanwhile, create your own CSS file to include your customizations. Name it custom.css (don't worry, I'll show you how to change that default name later).
  7. Upload your custom.css to your root style library (located at https://[yourtenant] If you have versioning enabled on that library, you may have to check-in the file so that other people can see your custom css. Again, don't worry, I'll show you how to use a different location later.
  8. Your custom CSS should show up!

The most important part of this is that the custom.css is NOT part of the SPFx solution! It is a separate file stored in a publicly-accessible location.

Frequently Asked Questions

It doesn't work!

.ms-compositeHeader-topWrapper {
    margin-top: 5px !Important;
    background-color: green;

if the above CSS works (by adding an ugly green bar at the top of the page), it means that the extension works and is able to load the custom CSS. Verify your CSS.

  • Using your browser's developer extensions, check to see if you're getting any kind of HTTP 404 (Not Found) message. If you're getting a 404, your CSS is named wrong or in the wrong place.

It works, but only for me (and other administrators)

  • You probably didn't check-in and publish your CSS.

The CSS doesn't get packaged in my solution!

Why doesn't the CSS get packaged in the solution?

  • I wanted to avoid having to re-deploy the solution every time I wanted to change the CSS.
  • I wanted non-developers to be able to use the application extension.

How do I change the name of the CSS?

  1. Rename your CSS to whatever you want
  2. Upload it to your root style library
  3. Go to your Tenant Wide Extensions (located at: https://[yourtenant]
  4. Select the InjectCssApplicationCustomizer from the list.
  5. Select Edit Item from the ribbon.
  6. In the edit form, change the value in Component Properties to use your new CSS name and hit Save. For example, if you renamed your CSS to contoso.css, you'd change the entry to be:

How do I place the CSS somewhere else than the root style library?

  1. Place your CSS in a publicly accessible library
  2. Go to your Tenant Wide Extensions (located at: https://[yourtenant]
  3. Select the InjectCssApplicationCustomizer from the list.
  4. Select Edit Item from the ribbon.
  5. In the edit form, change the value in Component Properties to use your new CSS name and hit Save. For example, if you created a new style library called InjectCss in the root site, you'd change the entry to be:

How do I place the CSS in a CDN?

  • I didn't test it. but in theory, you could follow the instructions above, but change the cssurl value to include the full path to your CDN.

How do I do [insert your own customization] by injecting CSS?

I'm not a CSS expert, but here's how I usually do my customizations:

  1. Using your browser, surf to a modern page.
  2. Launch your browser's developer toolbar (CTRL-Shift-I for Chrome, F12 for Edge)
  3. Use the element selector (CTRL-Shift-C for Chrome, Ctrl-B for Edge) select the element you want to customize.
  4. From the Styles pane in the developer tools, select + (New Style Rule) and enter the styles you want to change. Both Chrome and Edge has autocomplete capabilities, so feel free to explore. Don't worry, it only changes your current page, and does not gets saved if you refresh the page or load a new page.
  5. If you find that your styles are getting overwritten as soon as you apply them, try adding an !important instruction at the end of your style. (CSS experts are cringing as they read this).
  6. Once your element looks the way you want it, copy the rule to your custom CSS and upload the CSS wherever your placed it in your tenant.

Did I forget anything?

If there is anything I forgot, please let me know in the comments. I'll try to answer every question... eventually.


Independent consultant. Certified SCRUM Master. SharePoint, Office 365 and Dynamics 365 are his favourite toys.


  1. Pankaj Sukheja Reply

    I am not want to deploy it for all sites and css path should not be from root site this is possible?

    • Pankaj Sukheja Reply

      Can we specific css path other than root site collection? And i have deploy extension and make available on subsites on demand. By default it is not available for all. And it is working fine for me.can we give css path other than root site collection?

      • Hugo Bernier

        You can specify any path you wish, but you need to make sure the CSS can be accessed from any site collection where you want the extension to run.

        I hope this answers your question?

  2. Pankaj Sukheja Reply

    I have try same and it is working fine for root site collection. But when i try to use it another site collection it is not working. Please let me know what changes i have to do to use it in another site collection.

    • Hugo Bernier Reply

      Hi Pankaj,

      The extension must be deployed on all sites you wish to apply the custom CSS.

      If that is already done, make sure that your CSS path is an absolute path (i.e.: starts with a ‘/’), so that the CSS path can be resolved from all sites.

      One way to verify in your browser is look for a ‘404’ (Page Not Found) error on the Network tab of your browser’s developer toolbar. If the extension is running but the CSS does not apply, I suspect that it just can’t find the resource.

      I hope this helps?

      • Pankaj Sukheja

        I not want to deploy it on all site collections.and also css library path should not be on root site collection.can we place css file on any other site collection ?

      • Hugo Bernier

        No, unfortunately the extension must run on all site collections that require the custom CSS.

        When you deploy the extension, you should be prompted to deploy to all site collections. It is the option you should use to do that.

  3. Yash Shrivastava Reply

    every time I reload the page with new css, I had to clear the cache first and then reload. Is there any way to resolve this issue like if we can add a version number in css so that every time it gets freshly loaded

    • Hugo Bernier Reply

      You could change the extension configuration JSON file to add a unique value (e.g.: ?v=1, ?v=2, etc.) every time you want to force refreshing a new version?

  4. solution deployed. css injected. Seems to work. Only thing I absolutely CANNOT change is anything regarding the global nav. NOTHING I add works. It it ignored.

    Has ANYONE had any success? I really just want simple changes (font-weight, etc.)

    • Hugo Bernier Reply


      What do you mean by “global nav”? Do you mean the suite navigation (a.k.a. the “Waffle”)? It is often injected **after** the page is loaded, so it may be difficult to manipulate it.

  5. Evgeny Trifonov Reply

    Hi, thnx for your solution. I spent about 2 day to found it. My case was in change CSS in modern list view with grouping and I did it with your help.

    But I have a question. Your solution is wide-web and one css-file affects on all lists. Is there the some way to select list? Because now all my lists, even system looks alike and I need aplly custom.css to only one.

    I think, we can add this opportunity to solution, but I am not programmer šŸ™

    P.S. Sorry for my crazy English.

  6. Hugo – if I wanted to add multiple links to stylesheets in ClientSideComponentProperties, are they separated by a comma, or nothing? And is this the best practice? I tried it and both stylesheets appear in the source code, but only the 2nd one seems to get rendered.

    • Hugo Bernier Reply


      I designed the extension to handle one CSS at a time, but you can add the extension as many times as you’d like. It wouldn’t take much to change the code to handle multiple CSS, though. Let me know if you can’t add the extension more than once and I’ll find some time to update the sample.

      • Thanks Hugo! We’re looking to add a couple of security trimmed stylesheets to manage what users can access, and I think it would be useful to have everything in one extension, if you get the time to update the code. Meanwhile I’ll add another extension or 2..

  7. Florian Hein Reply

    Been looking for a week for a viable solution and I’m so glad I found yours. Thanks for your contribution.

  8. Henry Radke Reply

    Hey, thanks for this article! I managed it to apply the .css via gulp serve but had problems while trying to deploy it for production (gulp bundle –ship -> gulp package-solution –ship).

    The problem was that I added the .sppkg file on the http:// AppCatalog-URL. So I had to open the AppCatalog via https:// and then the deployment worked flawlessly!

    Maybe this is something you could add to your FAQ section, because I think that this could be the same problem, the other two commentators may had :).

    • Hugo Bernier Reply

      That’s a great catch! I’ll make a note in the article, thank you!

    • Hugo Bernier Reply

      Nandita, I’d be happy to help. Can you tell me what steps you followed so that I can diagnose the issues?

  9. Pasqualino Reply

    Hugo thank you so much, your extension and your advices have been invaluable to me

How can I help?

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: