Nick
Nick

Reputation: 14283

How to create a proper class structure?

I'm using LESS as css compiler.

Everything works fine, but now I need to create a specific class structure and I'm a bit stuck.

I'd like to have this structure:

.default .{color} {.icon-after/.icon-before} {.icon}

this is the code that I've done:

.default {

  &.disabled {
    background: lighten(@grayBackground, 5%);
    color: lighten(@darkText, 35%);
    cursor: default;
    border: @grayBorder;
    text-shadow: @grayTextShadow;
  }

  &.gray {
    background: @grayBackground;
    color: @darkText;
    border: @grayBorder;
    text-shadow: @grayTextShadow;
    &:hover {
      background: darken(@grayBackground, 5%);
    }
  }

  &.green {
    background: @greenBackground;
    border: @greenBorder;
    color: @lightText;
    text-shadow: @greenTextShadow;
    &:hover {
      background: darken(@greenBackground, 10%);
    }
  }

  &.yellow {
    background: @yellowBackground;
    border: @yellowBorder;
    color: @lightText;
    text-shadow: @yellowTextShadow;
    &:hover {
      background: darken(@yellowBackground, 10%);
    }
  }

  &.blue {
    background: @blueBackground;
    border: @blueBorder;
    color: @lightText;
    text-shadow: @blueTextShadow;
    &:hover {
      background: darken(@blueBackground, 10%);
    }
  }

  &.black {
    background: @blackBackground;
    border: @blackBorder;
    color: @lightText;
    text-shadow: @blackTextShadow;
    &:hover {
      background: darken(@blackBackground, 10%);
    }
  }

  &.red {
    background: @redBackground;
    border: @redBorder;
    color: @lightText;
    text-shadow: @redTextShadow;
    &:hover {
      background: darken(@redBackground, 10%);
    }
  }

  &.icon-before{
    .IconDefaultStyleBefore
  }

  &.icon-after{
    .IconDefaultStyleAfter()
  }
}

obviously this doesn't work, as the result is something like this:

.default .{color / .icon-after / .icon-before}

Any suggestions on how can I obtain my structure?

Thanks a lot

EDIT

I'd like to add the classes to the buttons in this order:

so, for example, adding this classes:

.default .blue .icon-before .tick

I will have:

default blue button with the tick icon before the text

Hope is now more clear than before.

Upvotes: 1

Views: 134

Answers (2)

Harry
Harry

Reputation: 89750

The required structure can be achieved as shown in the below example. The code can be simplified a lot by using loops (guarded mixins).

Explanation:

  1. @colors - An array list variable which has the list of colors required for the element.
  2. @bckground - Another array list variable which holds the required background color for each color class declared in the @colors list.
  3. e(extract(@colors, @index)) and extract(@bckground, @index) - Extract functions are used to fetch the color name and background color value corresponding to the index of each array iteration (similar to colors[i]). e() function is used to extract the color values without the quotes.
  4. &.@{color} - Selector interpolation to form the selector value. & is the parent selector and @{color} is the name of the color from the @colors list variable.
  5. length(@colors) - The no. of color items present in the @colors array list variable. This is passed to the loop function to tell the Less Compiler as to how many times the loop should be executed.
@colors: "red","green","black","blue","gray"; 
@bckground: #AAA, #0F0, #00F, #000, #F00;

.loop-colors(@index) when (@index > 0){ // loop to generate rules for each color
   .loop-colors(@index - 1);// call for the next iteration
   @color: e(extract(@colors, @index));
   @bgColor: extract(@bckground, @index);

   &.@{color}{
      background: @bgColor; //set background
      /* all other props */

      &:hover {
          background: darken(@bgColor, 5%);
      }

      &.icon-before{
          .IconDefaultStyleBefore;
      }

      &.icon-after{
          .IconDefaultStyleAfter();
      }
   }
}

.default{
    .loop-colors(length(@colors));
}

Note: As seven-phases-max mentioned in his comment, we are essentially generating a selector structure like .default.red.icon-before. Such a selector would essentially mean the same element has all the three classes and so even if it is specified like .default.icon-before.red it wouldn't make any difference but I assume that you are trying to make a more readable structure (like a default red button with an icon-before).

Upvotes: 2

ersoma
ersoma

Reputation: 1

.default{
  [...]    

  &.gray, &.black, [...every color...] {
    .icon-before{
      [...]
     }
  }
}

EDIT: or if you need a different .icon-before for every color you have to insert it one by one:

.default{
 [...]

     &.gray{
     [...]
         .icon-before{
          [...]
          }
     }
}

Upvotes: 0

Related Questions