7

Getting to grips with LESS here but one thing is still a little unclear.

Lets say I have multiple color themes for my website, controlled by a class on the body tag. From this I can redefine the various colors for each element within each theme. Easy enough but fairly time consuming if I have a lot of elements to change... and a lot of themes. Every time I add a new theme I need to write out all the selectors again, with different color values.

I am basing my working so far on another post I found: LESS.css variable depending on class

... However it still seems overly complicated for what I want to do in that I still have to write out all the selectors and include the mixin before dropping in the same CSS with the color variable.

I have created a CODEPEN HERE

I'd appreciate it if anyone had time to take a little look and advise me how I could approach this differently or how I could streamline this process.

Many thanks to anyone who helps out :)

Community
  • 1
  • 1
user1814828
  • 85
  • 1
  • 1
  • 3
  • 1
    Is there a reason you want your "themes" to all be in the same CSS file? It seems like it would be a hell of a lot simpler to just use alternate style sheets with one theme per file. – cimmanon Mar 07 '13 at 16:09
  • Hi cimmanon. If I was just using CSS I would go down that route. I just thought that there might be an easy way of changing the actual variable value after it had been declared, meaning that I would only really need a couple of lines of less to say what the new variable colors were within ".theme-2" and everything would then change colour in association with these new variable values. Thanks for your suggestion though. – user1814828 Mar 07 '13 at 17:44
  • I do understand what you're wanting, but you haven't answered my question. Creating 1 theme per file would be the simplest way to go about theming and would allow the user to avoid downloading styles they don't need because they'll never use anything other than their chosen (or default) theme. If each page has its own theme (ie. themes aren't configurable), then going with individual style sheets doesn't make much sense. – cimmanon Mar 07 '13 at 17:52
  • Ahhh, I see your point now, my apologies. I got so mixed up with the actual LESS I totally forgot to consider the unnecessary styles that would be downloaded.In this particular case I would like different pages to have the ability to have a different color theme which would be set by the creator in the CMS. I may have given a bad example here. I suppose at the end of the day what I am trying to find out is if a variable's value can be set to a different value within a particular parent class. In my head, this seemed like an easier way to maintain different color themes. – user1814828 Mar 07 '13 at 18:37

1 Answers1

19

Assuming you remain with wanting to theme it within one style sheet (and not multiple sheets as cimmanon noted in the comments), and assuming you are using LESS 1.3.2+, then the following code works to reduce the amount of duplication by setting up a loop through the classes that need theme changes.

Note that this does not work on Codepen (it is throwing an error uncaught throw #, perhaps because they are running an earlier version of LESS), but you can see it compiling correctly by putting the code into LESS's compiler.

LESS (based off your Codepen code with an added theme for demo)

//////////////////////////////////////////////////////
// CONSTANTS

@lightColour: #fff;
@darkColour: #000;
@lightBg: #fff;
@darkBg: #000;
@numberOfThemes: 3; //controls theme loop

//////////////////////////////////////////////////////
// MIXINS

//Theme Definitions by parametric mixin numbers (1), (2), etc.
.themeDefs(1) {
  @lightColour: #f00;
  @darkColour: #fff;
  @lightBg: #f00;
  @darkBg: #fff;
}

.themeDefs(2) {
  //inverse of 1
  @lightColour: #fff;
  @darkColour: #f00;
  @lightBg: #fff;
  @darkBg: #f00;
}

.themeDefs(3) {
  @lightColour: #cfc;
  @darkColour: #363;
  @lightBg: #cfc;
  @darkBg: #363;
}


.curvy {
  -moz-border-radius: 5px;
  -webkit-border-radius: 5px;
  border-radius: 5px;
}

//////////////////////////////////////////////////////
// GENERAL STYLING

* {padding: 0;margin: 0;}
html {text-align: center;}
h2 {padding: 20px 0;}

.box {
  .curvy;
  color: @lightColour;
  background: @darkBg;
  display:inline-block; width:10%; padding:20px 5%; margin:0 1% 20px 1%;
}

//////////////////////////////////////////////////////
// THEME BUILDING

.buildThemes(@index) when (@index < @numberOfThemes + 1) {

  .theme-@{index} {
      .themeDefs(@index); 
      color: @lightColour;
      background: @darkBg; 

      .box {
        color: @darkColour;
        background: @lightBg;
      }
    }
    .buildThemes(@index + 1);
}
//stop loop
.buildThemes(@index) {}
//start theme building loop
.buildThemes(1);

CSS Output (only showing the looped theme css for brevity)

.theme-1 {
  color: #ff0000;
  background: #ffffff;
}
.theme-1 .box {
  color: #ffffff;
  background: #ff0000;
}
.theme-2 {
  color: #ffffff;
  background: #ff0000;
}
.theme-2 .box {
  color: #ff0000;
  background: #ffffff;
}
.theme-3 {
  color: #ccffcc;
  background: #336633;
}
.theme-3 .box {
  color: #336633;
  background: #ccffcc;
}
ScottS
  • 71,703
  • 13
  • 126
  • 146
  • Thanks very much for this ScottS. I'll try that out with the correct version of LESS. This code snippet will be very handy for me in future, especially for smaller areas of CSS. I think it will be a case of taking both your and cimmanon's comments on board in future and deciding on the best solution for the given task. Thanks for both of your answers. – user1814828 Mar 07 '13 at 20:30
  • My less version is 2.2.0 but it doesn't work. I have an error on : .buildThemes(@index) when (@index < @numberOfThemes + 1) – Steven Mouret Jan 16 '15 at 08:51
  • 1
    Good writing is : .buildThemes(@index) when (@index < (@numberOfThemes + 1)) – Steven Mouret Jan 16 '15 at 09:18
  • @ScottS can you show me how to combine both theme 2 and 3, something like .themeDefs(2) + .themeDefs(2) { // something... } – minhhungit Nov 25 '20 at 13:20