Unlock CSS in Power Apps HTML Controls via Custom PCF

C
Collab365 TeamAuthorPublished Mar 29, 2026
2,321

At a Glance

Target Audience
Power Apps Developers, Low-Code Makers
Problem Solved
Standard HTML Text Control only supports inline styles, making CSS classes, pseudo-elements, and maintainable styling impossible.
Use Case
Rich HTML reports, dashboards, or dynamic content in Power Apps needing scalable CSS styling like alternating formats or responsive layouts.

Most developers look at the standard Power Apps HTML Text Control and see freedom. It never works out that way. You start with good intentions. You want to apply size, color, and alignment to your text. Then you realize the trap.

The standard control forces you to use inline styling. You can see this exact limitation discussed in the Community Showcase With Dale Morrison. Dale's app styles 23 paragraphs across 4 screens. If he wants to emphasize a paragraph, he has to inject a massive style attribute directly into the HTML tag.

<p>A normal paragraph.</p>
<p style="color: red; font-size: 1.2rem; font-weight: bold; text-decoration: underline;">A highly emphasised paragraph!</p>

inline styling examples
inline styling examples

This is a maintenance nightmare. Writing inline styles quickly escalates into a complex, repetitive mess. Your HTML becomes unreadable.

Real web development uses Cascading Style Sheets (CSS). CSS handles 12x more selectors than inline styling. You define a class once. You apply it everywhere.

<html>
  <head>
    <style>
      p.emphasis {
        color: red;
        font-size: 1.2rem;
        font-weight: bold;
        text-decoration: underline;
      }
    </style>
  </head>
  <body>
    <p>A normal paragraph.</p>
    <p class="emphasis">A highly emphasised paragraph!</p>
  </body>
</html>

Update the CSS file once, and every paragraph changes. You also get access to pseudo-elements and pseudo-classes. You can style the first line of a paragraph or alternate row colors. Inline styles cannot do this. But the standard HTML Text Control completely ignores CSS.

Stop waiting for standard controls to catch up. Build your own.

The Power Apps Component Framework (PCF) lets you write custom code components. The community has already built hundreds of these over at the PCF Gallery. Connor Deasey, a Collab365 Coach, recently demonstrated how to install an iFrame PCF Component. That got me thinking.

I am not a professional developer. I had never built a PCF component. But I wanted global CSS in my Power Apps. So I built one.

Building The Component

I followed Microsoft’s tutorial for creating a first component.

My approach was simple. I named the component HTMLControl. I gave it two text properties. One for the HTML string. One for the CSS string. The component appends a div to the standard container and injects a style element directly into the document head.

Here is the exact terminal command to start:

pac pcf init --namespace HTMLControlNamespace --name HTMLControl --template field --run-npm-install

Next, I updated the manifest file to define the properties. I set the property type to Multiple. This is crucial. It allows the string to be multiline and hold up to 1,048,576 characters. That is plenty of room for heavy code.

<property name="HtmlString" display-name-key="HTML String" description-key="A text string containing the HTML to display in the control." of-type="Multiple" usage="bound" required="false" />
<property name="CssString" display-name-key="CSS String" description-key="A text string containing the CSS to style the HTML displayed in the control." of-type="Multiple" usage="bound" required="false" />

In the index.ts file, I wrote the init method. This creates the elements and assigns IDs so we can target them later in our CSS.

private _container: HTMLDivElement;
private _css: HTMLStyleElement;

public init(context: ComponentFramework.Context<IInputs>, notifyOutputChanged: () => void, state: ComponentFramework.Dictionary, container:HTMLDivElement): void {
    this._css = document.createElement('style');
    this._css.setAttribute('id','CssContainer');
    this._css.innerHTML = context.parameters.CssString.raw ?? '';
    document.getElementsByTagName("head")[0].appendChild(this._css);

    this._container = document.createElement('div');
    this._container.setAttribute('id','HtmlContainer');
    this._container.innerHTML = context.parameters.HtmlString.raw ?? '';
    container.appendChild(this._container);
}

Then I added the updateView method. This simply updates the content whenever the Power App sends new data.

public updateView(context: ComponentFramework.Context<IInputs>): void {
    this._css.innerHTML = context.parameters.CssString.raw ?? '';
    this._container.innerHTML = context.parameters.HtmlString.raw ?? '';
}

Notice the ?? '' syntax. That is the nullish coalescing operator. If a property is left blank in Power Apps, it passes an empty string instead of a null value. This prevents JavaScript from throwing an error when it tries to update the innerHTML.

Using the Component

I packaged the code and followed the Microsoft Guide to enabling PCF components to import it into my environment.

It worked instantly.

One quick fix is required. If you load a massive HTML document, the component will stretch off the screen. Just drop the PCF control inside a vertical container and set the Vertical Overflow property to Scroll.

Here is what this custom control actually lets you do. I linked the HTML and CSS properties to a gallery of snippets. This completely eliminates the need for inline styling.

Example 1: Paragraph formatting

I used the nth-child pseudo-class to alternate paragraph colors automatically. If you did this with inline styles and someone added a new paragraph in the middle, you would have to manually recolour every single line below it.

I also used the first-line pseudo-element to emphasize the start of each section. You literally cannot do this with inline styles because you never know where a line break will happen on different screen sizes.

picture4
picture4

Example 2: Responsive elements

This is where CSS shines. I used a media query to change the container's background color based on the browser window size. I targeted the #HtmlContainer ID we created in the TypeScript file.

Large Browser Window

picture3
picture3

Small Browser Window

picture2
picture2

In the real world, you would not just change colors. You would adjust font sizes, shift layouts, or hide elements entirely based on the user's screen.