1

I have a collection of li, each with different background colors like these:

                    &.menu-white {
                        background-color: @product-white;
                        color: darken(@product-white, 20%);
                    }

                    &.menu-green {
                        background-color: @product-green;
                        color: darken(@product-green, 20%);
                    }

                    &.menu-yellow {
                        background-color: @product-yellow;
                        color: darken(@product-yellow, 20%);
                    }

                    &.menu-black {
                        background-color: @product-black;
                        color: lighten(@product-black, 20%);
                    }

                    &.menu-red {
                        background-color: @product-red;
                        color: darken(@product-red, 20%);
                    }

Now I need to make the background color darkens according to its current background color when mouse is hovered. If possible, I don't want to add so many &:hover on each of the menu, so here's what i tried:

&:hover {
     background-color: darken(inherit, 10%);
}

This is not working, is there any efficient way where i can do &:hover only one time and it affects all the lis?

--EDIT--

Following @seven-phase-max suggestion I updated the code into something like this

@product-types: white #E2E0DE,
            green #95CFAB,
            yellow #FEC63E,
            black #505858,
            red #EE5C60;

.menu-lists() {
    .-(5);
    .-(@i) when (@i > 0) {
        .-((@i - 1));

        @type: extract(@product-types, @i);
        @color: extract(@type, 1);
        &.menu-@{color} {
            background-color: extract(@type, 2);
            color: darken(extract(@type, 2), 50%);

            &:hover {
                background-color: darken(extract(@type, 2), 10%);
            }
        }
    }
}

That works fine, except that the white, red, etc, is translated into hex color (menu-#ffffff, menu-#ff0000). It did work when i changed it to:

@product-types: menu-white #E2E0DE,
            menu-green #95CFAB,
            menu-yellow #FEC63E,
            menu-black #505858,
            menu-red #EE5C60;

.menu-lists() {
    .-(5);
    .-(@i) when (@i > 0) {
        .-((@i - 1));

        @type: extract(@product-types, @i);
        @color: extract(@type, 1);
        &.@{color} {
            background-color: extract(@type, 2);
            color: darken(extract(@type, 2), 50%);

            &:hover {
                background-color: darken(extract(@type, 2), 10%);
            }
        }
    }
}

But is there any way so I could use the first solution? (ex. translate white as "white" not "#ffffff")

seven-phases-max
  • 11,765
  • 1
  • 45
  • 57
user2002495
  • 2,126
  • 8
  • 31
  • 61
  • You can use mixins, lists and loops to get rid of these copy-pastes. See for example a very similar http://stackoverflow.com/questions/19745208 – seven-phases-max Nov 19 '13 at 12:59
  • Speaking of those `~'white'`, `'white'` and `#ffffff` things: this most likely will be improved in LESS 1.6.x, see [#1595](https://github.com/less/less.js/issues/1595), [#1604](https://github.com/less/less.js/pull/1604). So then we'll be able to write just `white` instead of those ugly `'~white'` or `e('white')`. – seven-phases-max Nov 19 '13 at 14:06
  • since i used grunt to compile my .less (the less version of grunt currently is below 1.5), i expect the updates are still a long way – user2002495 Nov 20 '13 at 07:08

1 Answers1

3

Use LESS mixins, lists and loops to generate a repetitive CSS code:

@product-colors:
    white  #fff,
    green  #0f0,
    yellow #ff0,
    black  #000,
    red    #f00;

.menu-template(@name, @color) {
    &.menu-@{name} {
        background-color: @color;
        color: darken(@color, 20%);
        &:hover {
             background-color: darken(@color, 10%);
        }
    }
}

.make-menus() {
    .-(length(@product-colors));
    .-(@i) when (@i > 0) {
        .-((@i - 1));
        @value: extract(@product-colors, @i);
        @name:  extract(@value, 1);
        @color: extract(@value, 2);
        .menu-template(@name, @color);
    }
}

li {
    .make-menus();
}

It is possible to use the .menu-template mixin directly without need for the @product-colors list and the corresponding loop. This actually results in a shorter and more readable code (until you need these colors to generate some other repetitive CSS classes):

li {
    .menu-template(white,  #fff);
    .menu-template(green,  #0f0);
    .menu-template(yellow, #ff0);
    .menu-template(black,  #000);
    .menu-template(red,    #f00);
}
seven-phases-max
  • 11,765
  • 1
  • 45
  • 57