Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Programmatically change the primary color used in several places in the CSS

The primary color of my Single Page Application is programmatically client-side defined. The problem is that is it used in many places in my code.

Eg. on load, I have (in SCSS):

body {
  background-color: #XXXXXX;
}

.btn-primary {
  background-color: #XXXXXX;
}

.content ul li a {
  color: #XXXXXX;
  border: thin solid #XXXXXX;
  &:hover {
    background-color: #XXXXX;
    color: white;
  }
}

And I need to replace#XXXXXX to #YYYYYY everywhere, on the client side.

The different options I see are:

1. isolate the color-related CSS, and wrap it with a class

Something like:

body {
  background-color: #XXXXXX;
  .btn-primary {
    background-color: #XXXXXX;
  }

  .content ul li a {
    color: #XXXXXX;
    border-color: #XXXXXX;
    &:hover {
      background-color: #XXXXX;
    }
  }

  &.other-color {
    background-color: #YYYYYY;
    .btn-primary {
      background-color: #YYYYYY;
    }

    .content ul li a {
      color: #YYYYYY;
      border-color: #YYYYYY;
      &:hover {
        background-color: #YYYYYY;
      }
    }
  }
}

+ Pro It will eventually work

- Con Not DRY at all!

2. Using a dirty JS that would inspect every occurences of #XXXXXX and replace with #YYYYYY in the DOM.

+ Pro Seems clean to me

- Con Not sure it is doable

3. Using a dirty JS that would inspect every occurences of #XXXXXX and replace with #YYYYYY in the CSS file.

+ Pro Should do the job

- Con Not sure it is doable. And it doesn't feel like the right way to do it.

4. Compile several times the application.css to application-other-color.css and use it accordingly.

+ Pro Pretty easy to implement (compared to the other solutions)

- Con The user needs to load different assets, which is not optimum for a SPA

Has anyone faced this issue before? Is there any better solution than those two? If not, which one would you suggest? Did I miss some pros/cons?

like image 386
Augustin Riedinger Avatar asked Aug 12 '15 16:08

Augustin Riedinger


2 Answers

Basically, #1, but I would structure it differently. It's best to separate these if they are indeed different states/classes, and name them semantically.

That way, if you decide, for example, that .body-content--error also needs to have green text, or whatever, you can easily edit it in. Now you just need to set the javascript to switch classes, which is simple.

This is actually very DRY code, in that .body-content and .body-content--error are different states of the same element. In fact, with the code below, you can set the class of body to class="body-content body-content--error" and inherit all of the .body-content CSS, and just change the background-color with .body-content--error.

$primary-color: #XXXXXX;
$error-color: #YYYYYY;

// Body content
.body-content {
  background-color: $primary-color;
  margin: 10px;
  padding: 10px;
}
.body-content--error {
  background-color: $error-color;
}

//Button (primary)
.btn-primary {
  background-color: $primary-color;
}
.btn-primary--error {
  background-color: $error-color;
}

// Links in the .content list
.content-list-link {
  color: $primary-color;
  border-color: $primary-color;
  &:hover {
    background-color: $primary-color;
  }
}
.content-list-link--error {
  color: $error-color;
  border-color: $error-color;
  &:hover {
    background-color: $error-color;
  }
}
like image 187
MattDiamant Avatar answered Oct 03 '22 22:10

MattDiamant


CSS variables seem the perfect solution:

body {
  --my-color: red;                   /* Set some value */
  background-color: var(--my-color); /* Use the value in the variable */
}
.btn-primary {
  background-color: var(--my-color); /* Use the inherited value */
}

Then, changing the colors is simple:

document.body.style.setProperty('--my-color', newColor);

document.querySelector('button').onclick = function() {
  var rndcolor = '#' + ('00000' + Math.floor(Math.random() * 256 * 256 * 256).toString(16)).slice(-6);
  document.body.style.setProperty('--my-color', rndcolor);
};
body {
  --my-color: red;
  background-color: var(--my-color);
}
.content {
  background-color: #fff;
  padding: 20px;
}
.btn-primary {
  background-color: var(--my-color);
}
.content a {
  color: var(--mycolor);
  border: thin solid var(--my-color);
}
.content a:hover {
  background-color: var(--my-color);
  color: white;
}
<div class="content">
  <button class="btn-primary">Click me to change color</button>
  <a>I have a border</a>
</div>

The problem is that CSS variables are not widely supported yet.

like image 39
Oriol Avatar answered Oct 03 '22 20:10

Oriol