Code with Benji
Code with Benji

Reputation: 727

How to dynamically change Bootstrap v5.3 primary color at runtime in Angular v17?

I am working on an Angular application that uses Bootstrap for styling. I want to allow users to select a theme color, and dynamically update the Bootstrap primary color (--bs-primary) at runtime without reloading the page.

Currently, Bootstrap’s primary color is defined in SCSS like this:

$primary: #0d6efd; 
@import "bootstrap/scss/bootstrap";

However, this approach requires recompilation, and I need a way to change the primary color dynamically via JavaScript or TypeScript.

What I Have Tried CSS Variables I attempted to override the Bootstrap primary color using CSS variables:

:root {
    --bs-primary: #{$primary};
}

But this does not seem to work for all Bootstrap components like buttons and alerts.

Using JavaScript to Update Variables I also tried updating CSS variables dynamically in TypeScript:

  changeThemeColor(color: string): void {
    document.documentElement.style.setProperty('--bs-primary', color);
    const primaryRgb = this.hexToRgb(color);
    if (primaryRgb) {
      document.documentElement.style.setProperty('--bs-primary-rgb', `${primaryRgb.r}, ${primaryRgb.g}, ${primaryRgb.b}`);
    }
  }

However, this change above its only the span with text-primary that gets to reflect the changes of the new color and the button does not

<span class="text-primary">Primary Text</span>
<button class="btn btn-primary">Primary Button</button>

Upvotes: 1

Views: 59

Answers (1)

Naren Murali
Naren Murali

Reputation: 57986

These are the styles of the btn-primary, As you can see they are not derived from variables but defined directly.

.btn-primary {
    --bs-btn-color: #fff;
    --bs-btn-bg: #0d6efd;
    --bs-btn-border-color: #0d6efd;
    --bs-btn-hover-color: #fff;
    --bs-btn-hover-bg: rgb(11.05, 93.5, 215.05);
    --bs-btn-hover-border-color: rgb(10.4, 88, 202.4);
    --bs-btn-focus-shadow-rgb: 49, 132, 253;
    --bs-btn-active-color: #fff;
    --bs-btn-active-bg: rgb(10.4, 88, 202.4);
    --bs-btn-active-border-color: rgb(9.75, 82.5, 189.75);
    --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
    --bs-btn-disabled-color: #fff;
    --bs-btn-disabled-bg: #0d6efd;
    --bs-btn-disabled-border-color: #0d6efd;
}

You can still override them with the below method. The font color of the first button is derived from '--bs-primary-rgb' so you can override this using your method.

The code will look something like below:

import { Component } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import { CommonModule } from '@angular/common';
@Component({
  selector: 'app-root',
  imports: [CommonModule],
  template: `
    <span class="text-primary">Primary Text</span>
    <button class="btn btn-primary" [ngStyle]="color ? {
      '--bs-primary-rgb': color,
        '--bs-btn-bg': color,
        '--bs-btn-border-color': color,
    } : {}">Primary Button</button>
    <button (click)="changeThemeColor('#DFDFDF')"> change color</button>
  `,
})
export class App {
  color: string | undefined;
  changeThemeColor(color: string): void {
    this.color = color;
    ['--bs-primary-rgb'].forEach((item: string) => {
      document.documentElement.style.setProperty(item, color);
    });
  }
}

bootstrapApplication(App);

Stackblitz Demo

Upvotes: 1

Related Questions