A guide on how to dynamically inject CSS using Angular

I've spent the past few days testing out different solutions, advice, and tutorials for this issue, but unfortunately none of them have worked.

The closest suggestion I found was from this link:

However, it references "extractCss," which has been deprecated since the article was published.

As per the guide:

  1. The "styles.js" file should no longer appear in Inspector > Network > JS
  2. Clicking a button should add its CSS file in Inspector > Network > CSS

Unfortunately, neither of these scenarios is occurring at present.

app.component.ts

  const head = this.document.getElementsByTagName('head')[0];
    console.log(head);
    let themeLink = this.document.getElementById(
      'client-theme'
    ) as HTMLLinkElement;
    if (themeLink) {
      themeLink.href = styleName;
    } else {
      const style = this.document.createElement('link');
      style.id = 'client-theme';
      style.href = `${styleName}`;
      head.appendChild(style);
    }
}

app.component.html

    <head>
    </head>
    <body>
        <button type="button" (click)="loadStyle('client-a-style.css')">STYLE 1</button> 
        <button type="button" (click)="loadStyle('client-b-style.css')">STYLE 2</button>     
    </body>
</html>

angular.json

"styles": [
              "src/styles.css",
              {
                "input": "src/client-a-style.css",
                "bundleName": "client-a",
                "inject": false
              },
              {
                "input": "src/client-b-style.css",
                "bundleName": "client-b",
                "inject": false
              }

This comprises the core elements of my code.

I hope that sufficiently clarifies the issue. Thank you in advance for your assistance!

Answer №1

To organize your additional .css files, simply place them in the assets folder and remove them from angular.json

After that, the only modification required is to include the "assets" folder in the href attribute

  loadStyle(styleName: string) {
    const head = this.document.getElementsByTagName('head')[0];

    let themeLink = this.document.getElementById(
      'client-theme'
    ) as HTMLLinkElement;
    if (themeLink) {
      themeLink.href = `assets/${styleName}`; //<--add assets
    } else {
      const style = this.document.createElement('link');
      style.id = 'client-theme';
      style.rel = 'stylesheet';
      style.type = 'text/css';
      style.href = `assets/${styleName}`; //<--add assets

      head.appendChild(style);
    }
  }

For a live example, check out this StackBlitz demo

Answer №2

Here is a viable solution for this task:

import { DOCUMENT } from '@angular/common';
import { Inject, OnDestroy, OnInit, Renderer2 } from '@angular/core';


export class MyComponent implements OnInit, OnDestroy {
  private style?: HTMLLinkElement;

  constructor(
    @Inject(DOCUMENT) private document: Document,
    private renderer2: Renderer2,
  ) {}

  public ngOnInit(): void {
    const cssPath = '/link/to/style.css';
    
    // Creating a link element using Angular's renderer to avoid issues with server-side rendering
    this.style = this.renderer2.createElement('link') as HTMLLinkElement;

    // Adding the style to the head section
    this.renderer2.appendChild(this.document.head, this.style);

    // Setting the type of the link item and the path to the CSS file
    this.renderer2.setProperty(this.style, 'rel', 'stylesheet');
    this.renderer2.setProperty(this.style, 'href', cssPath);
  }
  
  public ngOnDestroy(): void {
    // Remember to remove the style after destroying the component
    this.renderer2.removeChild(this.document.head, this.style);
  }
}

If your CSS files are on the server, you may need to update your proxy.conf.json file to grant access to these files from localhost while in serve mode.

Answer №3

It appears that there's a missing property in the link tag, make sure to include this when creating the link element for it to function properly.

style.rel = 'stylesheet';

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Using CSS to style an alternate list elements to float

I'm working on a webpage that displays messages from a database using ajax. Currently, the output is just stacked downwards. I'm hoping to style the list elements to alternate from left to right, similar to an iOS Message chat. Does anyone have ...

JS method for gradually reducing the opacity of various div elements

I currently have two divs with background images styled using CSS. My goal is to create a loop that fades them in and out continuously. While attempting to achieve this effect, I encountered some issues and the following code snippet doesn't seem to ...

Click to Rotate Image Icon

I could use some assistance with this task. I want to create a functionality where clicking on the text/icon causes the + icon to rotate 45 degrees, resembling an x icon. With each subsequent click, the icon should alternate between the + and x shapes. An ...

Steps for activating the "active" class on a selected menu item in the header.php file

In my header.php file, I have a few menu items. I am including the "header.php" file in various pages like About Us and Contact Us... How can I use PHP to highlight the selected menu item? <ul> <li><a href="<?php echo $ ...

When attempting to pass a numeric value to the @Input x property with two-way binding in Angular's strict template mode, an error is triggered

I am looking to enhance my application by implementing Angular's template Strict mode through the configuration of "strictTemplates": true within tsconfig.json. However, encountering an unexpected error after running ng serve with this updat ...

Questions about CSS

I am currently in the process of creating a new website and I am encountering some challenges. Here is a preview of the HTML/CSS: Specifically, I have some questions regarding the CSS: 1) Why does the hover effect only work on "OM OS" and "KONSULENT," bu ...

Modal obstructing BsDatePicker

<!-- The Server Modal --> <div class="modal" id="serverModal"> <div class="modal-dialog" style="max-width: 80%;overflow-y: initial !important;" > <div class=" ...

Switch between two fields using just one animation

I've been experimenting with creating an information tag that slides out from behind a circular picture. To achieve this effect, I created a block and circle to serve as the information field placed behind the image. However, I'm facing a challe ...

Retrieve an individual item from the observable array

How can I create a function that takes an Observable<T[]> and returns Observable<T>? Here is the scenario: I have two methods: getTransactions(): Observable<Transaction[]>{ ... } getTransaction(id: number): Observable<Tra ...

What about a lightbox with enhanced jQuery features?

As a newcomer to jQuery, I've never experimented with lightboxes before. However, I was tasked with creating something fun for April Fools' Day at work. Naively, I accepted the challenge thinking it would be simple, but now I find myself struggli ...

Toggle the visibility of images with input radio buttons

Explanation I am attempting to display an image and hide the others based on a radio input selection. It works without using label, but when I add label, it does not work properly. The issue may be with eq($(this).index()) as it ends up selecting a differ ...

"Enhance your user experience with Abp.io Commercial's Identity Module Localization

I've been struggling to locate proper documentation on how to change the identity module's Name and Surname fields to First Name and Last Name in a UI with Angular. We did not purchase the source code for ABP.io commercial. I've attempted va ...

What is the best way to include CSS code in the output display?

I'm looking to customize the appearance of my table rows and cells. Specifically, I want the cell file name, size, etc., to be colored blue while each row should have a different color on hover. I've attempted to achieve this using CSS and variou ...

Tips for updating the hover background color of a table row with a unique class in bootstrap

Modified: Here is the table along with its corresponding CSS styling: .table-hover tbody tr:hover { background-color: #fff !important; } <html lang="en"> <head> <meta charset="utf-8" /> <meta name="v ...

Retrieve the value of the input text once an option has been chosen from a JSON file using Angular 10

On my webpage, I have a selection with some input fields: <div class="form-row"> <div class="form-group col-lg-6"> <label>City*</label> <select formControlName='legalCity' class="form-co ...

Exploring the sharing of observables/subjects in Angular 2

UPDATE: After further investigation, it appears that the SharedService is being initialized twice. It seems like I may be working with separate instances, causing the .subscribe() method to only apply to the initiator. I'm not sure how to resolve this ...

Embedding content within a toggle slider

As a beginner in CSS, I have a simple question that needs addressing. I am unsure which class to begin with for my task. The goal is to insert text (specifically, two digits) neatly inside toggle buttons (the slider that moves and appears white). I am u ...

The browser does not store cookies in its memory

After conducting extensive research on this issue, I have not been able to find a solution yet. In essence, I am currently running a Node.js API server on localhost:3000 and an Angular 10 app on localhost:4200. The problem is straightforward - when I make ...

What is the process for integrating a dynamic search bar onto an Angular table?

I have a table and I want to add a search box above the table that dynamically searches through the data and filters it to make it easier for users to find what they are looking for. Here is the code for my table: <mat-card class="fields-list" *ngIf=" ...

Having trouble with GSAP CDN not functioning properly in your JavaScript or HTML document?

After watching a tutorial on YouTube by Gary Simon, I attempted to animate text using GSAP. Despite following the instructions meticulously and copying the CDN for GSAP and CSSRulePlugin just like him, nothing seems to be happening. Even setting my border ...