How can I change the primary color in Bootstrap 4 based on the body class?

I'm working on a website where each section is assigned a primary color. Now, I want to use Bootstrap 4's Sass code to dynamically change the primary color based on a body class I set.

Although I have attempted to do this with the following code, it hasn't been successful:

$theme-colors: () !default;
$theme-colors: map-merge((
    // primary: $blue,
    // secondary: $gray-600,
    success: $green,
    info: $cyan,
    warning: $yellow,
    danger: $red,
    light: $gray-100,
    dark: $gray-800
), $theme-colors) !default;

// override according to portal
html {
    &.portal-1 {
        $theme-colors: map-merge((
            primary: #f1b36d
        ), $theme-colors);
    }

Can anyone guide me on how to properly implement this feature in Bootstrap 4's Sass files?

Answer №1

It is not possible to dynamically change sass variables that have already been converted to static CSS on the client side. However, there are a few options you can consider for building a theme system:

1. Creating independent themes

Add a theme argument to your build system to generate different theme CSS files. For example: grunt build-sass --theme=brown

var themes = {
    "default": "https://bootswatch.com/flatly/bootstrap.min.css",
    "cerulean" : "https://bootswatch.com/cerulean/bootstrap.min.css"
}

// Use something like this to add a theme: (You can also append instead of overriding the whole head HTML)
var headHTML = document.getElementsByTagName('head')[0].innerHTML;
headHTML    += '<link type="text/css" rel="stylesheet" href="' + themes.cerulean +'">';
document.getElementsByTagName('head')[0].innerHTML = headHTML;

2. Adapting properties based on the parent class

You can have a base CSS file that defines general styles and then specific CSS properties based on the parent class.

In the example below, you can switch the green-theme class to blue-theme and vice versa:

div[class^=component] {
  display: inline-block;
  width:150px;
  height: 150px;
  margin: 1em;
  border: 1px solid black;
  box-shadow: 1px 1px 5px gray;
  border-radius:1em;
}

/* Colors*/
$blue1: #3066BE; 
$blue2: #090C9B;
$green1: #5C946E; 
$green2: #80C2AF;

/* Blue Theme */
.blue-theme {
  .component1 {
    background-color: $blue1;
  }
  
  .component2 {
    background-color: $blue2;
   }
}
/* Green Theme */
.green-theme {
  .component1 {
    background-color: $green1;
  }
  
  .component2 {
    background-color: $green2;
   }
}
<div class="green-theme" id="mainBody">
    <div class="component1">
    </div>
    
     <div class="component2">
    </div>
</div>

*Please note that the Run Snippet feature will not work as we are using SCSS.*

Answer №2

Create a structured scss file setup as shown below:

- vendors
  - bootstrap
    - stylesheets /*[Official Bootstrap 4 sass files]*/
      - _bootstrap.scss
- scss
  - themes
    - _theme-1.scss
    - _theme-2.scss
  - _variables.scss
  - styles.scss
  - portal-1.scss
  - portal-2.scss

_variables.scss

@import "../vendors/bootstrap/stylesheets/bootstrap/variables";
@import "../vendors/bootstrap/stylesheets/bootstrap/mixins";
/* override default bootstrap variables */
/* define custom variables with !default */

styles.scss

@import "variables";
@import "../vendors/bootstrap/stylesheets/bootstrap";
/* add custom styles */

themes/_theme-1.scss

@import "../variables";
/* modify bootstrap and custom variables */
$brand-primary:         #428bca
$brand-success:         #5cb85c;
$brand-info:            #5bc0de;
$brand-warning:         #f0ad4e;
$brand-danger:          #d9534f;
$body-bg:               #eff;

themes/_theme-2.scss

@import "../variables";
/* adjust bootstrap and custom variables */
$brand-primary:         #C04848;

portal-1.scss

@import "themes/_theme-1";
/* apply style changes using new bootstrap variables */
.portal-1 {
    @import "../vendors/bootstrap/stylesheets/bootstrap/buttons";
    @import "../vendors/bootstrap/stylesheets/bootstrap/alerts";
   /* customize styles here */
}

portal-2.scss

@import "themes/_theme-2";
/* apply style changes using new bootstrap variables */
.portal-2 {
    @import "../vendors/bootstrap/stylesheets/bootstrap/buttons";
    @import "../vendors/bootstrap/stylesheets/bootstrap/alerts";
   /* include custom styles from style.scss overrides */
}

Upon compilation, you will have styles.css, portal-1.css, and portal-2.css files. Include styles.css by default and the others in the head tag for theming.

<html>
    <head>
         <link href="styles.css" rel="stylesheet" />
         <link href="portal-1.css" rel="stylesheet" />
    </head>
    <body>
        <button class="btn btn-primary">BUTTON</button>
        <div class="portal-1">
            <button class="btn btn-primary">BUTTON</button>
        </div>
    </body>
</html>

Answer №3

After extensive searching for a simple solution, I stumbled upon a method that can save others the frustration of trying to achieve this:

CSS variables can be utilized to accomplish this task.

On the main bootstrap github page, there is a discussion regarding this issue Github Issue, where user @johanlef has shared a gist demonstrating his approach and the necessary code gist.

Simply ensure that the css variables are initialized on your page

.body.theme1{
   --primary: #5d8be5;
}

I have successfully implemented this method on one of my multi tenanted websites and it functions perfectly.

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

Styling Text on Buttons (Using CSS)

I need to modify my button, which contains lengthy text. When the mouse pointer hovers over the button, I would like the long text to wrap into 2 or 3 lines so that more of it is visible. Additionally, I want the remaining text to be displayed with an el ...

What is the process for connecting a personalized bootstrap framework with an index.html document?

I have recently dived into the world of bootstrap and I just customized my bootstrap file on http://getbootstrap.com/docs/3.3/customize/ After compiling and downloading, I found it challenging to link it with my index.html file. The source of the bootstra ...

Is there a specific CSS selector that targets elements with "multiline" content?

My website has a menu that displays with the following CSS: a { background:red; } <a href="#">Home</a> <a href="#">Downloads</a> <a href="#">Contact</a> <a href="#">FAQ</a> <a href="#">Disclaimer&l ...

Bootstrap 4: Concealed and Revealed Columns?

Is anyone else experiencing an issue where xs is hidden in xs views? I have a hunch it might be due to changes in Bootstrap v4, but I'm curious if there's a way to still make it work without delving into the CSS. My current setup uses the default ...

Creating a Dynamic Slideshow on Autopilot

My JavaScript skills are not perfect and I'm feeling a bit lost. I have this code for a slideshow, but I want to make it automatic while also allowing users to navigate between images freely. I'm struggling to figure out how to implement this fun ...

The v-bind:style directive in Vue.js is functioning properly for setting the margin-right property, however

Having an issue with applying a specific style to one of my div elements. When using the following code: :style="(index + 1) % 2 == (0) && type.Liste.length === indexVin + 1 ? `margin-left : calc((100% - (100% / ${type.Liste.length})) + 6rem); ...

Having Difficulty Modifying the CSS Styles of a Specific Class

I've been struggling with a CSS styling issue for some time now. The problem lies in targeting the class for the thumbnail preview of vue2-dropzone (which shares similar properties with dropzone.js based on documentation). Each time I upload an image, ...

I have a simple inquiry regarding the customization of table designs

I struggle with html/css, so I could really use some assistance. Here's a fiddle of a table link to fiddle. The td rows are currently the same width, but I want to set specific widths for each column - 200px for the left column and 50px for the right ...

What factors determine the height of a table cell?

My forehead is now a grid of indents after battling with HTML tables for days, leaving marks resembling my keyboard. Speaking of grids, I'm curious if there are any clear guidelines on the sizing of <td>. Does it depend solely on content? Is i ...

At the header of my webpage, there is a subtle grey border

As a beginner in the world of HTML website building, I am currently working on creating a fast food website. My goal is to have a "Home", "Menu", and "Contact" links at the top of my webpage, but I am struggling with adjusting the margin and padding. Here ...

Determine the present vertical measurement of the video

I am having trouble determining the actual height of a video element. Despite seeing in the developer tools that it is 384px, I am only able to retrieve a height of 342px. I attempted the following code snippet, but it only gives me the natural height, no ...

Use of carrots within a contenteditable div

Whenever I click inside this div for the first time, my cursor goes up. But when I start typing, the text appears correctly in the middle of the div. How can I resolve this issue with the placeholder not aligning properly? I want the cursor to be positione ...

Ways to create unique hover effects for images in a filter gallery

I recently downloaded a filter gallery from this link and while everything is working fine, I noticed that the hover effect remains the same for all images. The code snippet responsible for this hover effect looks like this: <div class="portfolio"> ...

Issue with arranging blocks in a horizontal line in Opera

I am currently experiencing an issue with a wide page that contains an information block and numerous images positioned to the right. The layout is designed to be used with a horizontal scrollbar. While this setup works perfectly in Firefox, Safari, Chrom ...

Tips for preserving the dimensions of a container even after adding text dynamically

I have created a form and implemented a JavaScript warning for when the entered passwords do not match. However, I am facing an issue where adding the warning text causes other elements in the container to shift. Is there a way to prevent this from happe ...

Unable to view Bootstrap modal upon click

Whenever I attempt to display a modal using Bootstrap, it mysteriously appears upon page refresh but fails to show up when the button is clicked. Ideally, I want the modal to only appear when the user clicks on the button. The structure of my html file lo ...

Adjust the text orientation using CSS within an SVG element

Here is the SVG code snippet that I am working with: https://jsfiddle.net/danpan/m3ofzrc1/. It generates the image shown below. The image consists of two lines of text wrapped around a circle: HELLO_WORLD_1 HELLO_WORLD_2 I want to change the direction ...

precise placement of image inside pop-up

Having trouble positioning an image (an arrow) within a pop-up window. Attempted relative positioning to move the image precisely, but facing difficulties. Decided to go with absolute positioning instead, nesting a div within another div as shown below: ...

dividing a circle in half with CSS using an image background

Is it possible to divide a circle into 2 parts using both RGB and URL images? Here is an example of how I want it to look: https://i.sstatic.net/r5sWj.png I have managed to write code that works with RGB, but I am unsure how to achieve the same effect w ...

Grid Refresh Spinner Update

Our Vaadin Grid features a settings icon that when clicked, opens a window allowing users to select/deselect columns. Upon closing this window (triggering our custom window event), the main window's columns are updated accordingly. Now, my requirement ...