Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Telling LESS CSS how to behave with .active li

I'm trying to make a menu which has 6 buttons and each of them has its own background color and hover background color. Now, I don't want the background color to show when hover if the link's parent li has an .active class. This is what I tried to do:

//I'm making li and li.active links to have the same normal and hover state bg color and then...
li, li.active{
    &:first-child{
        a, a:hover{
            background: @1-n;
        }
        + li{
            a, a:hover{
                background: @2-n;
            }
            + li{
                a, a:hover{
                    background: @3-n;
                }
                + li{
                    a, a:hover{
                        background: @4-n;
                    }
                    + li{
                        a, a:hover{
                            background: @5-n;
                        }
                        + li{
                            a, a:hover{
                                background: @6-n;
                            }
                        }
                    }
                }
            }
        }
    }
}
//..trying to overwrite the hovers only for normal li so I can't avoid applying them to li.active's ones
li{
    &:first-child{
        a:hover{
            background: @1-h;
        }
        + li{
            a:hover{
                background: @2-h;
            }
            + li{
                a:hover{
                    background: @3-h;
                }
                + li{
                    a:hover{
                        background: @4-h;
                    }
                    + li{
                        a:hover{
                            background: @5-h;
                        }
                        + li{
                            a:hover{
                                background: @6-h;
                            }
                        }
                    }
                }
            }
        }
    }
}

This is the CSS that is being generated:

li:first-child a, li.active:first-child a, li:first-child a:hover, li.active:first-child a:hover {
    background: @1-n;
}
li:first-child + li a, li.active:first-child + li a, li:first-child + li a:hover, li.active:first-child + li a:hover {
    background: @2-n;
}
li:first-child + li + li a, li.active:first-child + li + li a, li:first-child + li + li a:hover, li.active:first-child + li + li a:hover {
    background: @3-n;
}
li:first-child + li + li + li a, li.active:first-child + li + li + li a, li:first-child + li + li + li a:hover, li.active:first-child + li + li + li a:hover {
    background: @4-n;
}
li:first-child + li + li + li + li a, li.active:first-child + li + li + li + li a, li:first-child + li + li + li + li a:hover, li.active:first-child + li + li + li + li a:hover {
    background: @5-n;
}
li:first-child + li + li + li + li + li a, li.active:first-child + li + li + li + li + li a, li:first-child + li + li + li + li + li a:hover, li.active:first-child + li + li + li + li + li a:hover {
    background: @6-n;
}
li:first-child a:hover {
    background: @1-h;
}
li:first-child + li a:hover {
    background: @2-h;
}
li:first-child + li + li a:hover {
    background: @3-h;
}
li:first-child + li + li + li a:hover {
    background: @4-h;
}
li:first-child + li + li + li + li a:hover {
    background: @5-h;
}
li:first-child + li + li + li + li + li a:hover {
    background: @6-h;
}

I apologize if I messed up with my english, I hope I made myself clear!

Thanks!!!!

like image 436
user2122223 Avatar asked Mar 01 '13 05:03

user2122223


1 Answers

Updated Answer for Many Levels

This utilizes a variation of option 2 below in my original answer, which means LESS 1.3.1+ needs to be the version used. This actually ends up more readable in this case (in my opinion) because of the use of the variables. I've used just numbers (1) and then a number with "h" (1h) to represent the base background and the desired hover state background respectively.

LESS

ul {
    li {
        @first: ~':first-child';
        @withActive: ~'.active';
        @noHover: ~'a';
        @withHover: ~'a:hover';
        @level2: ~'+ li';
        @level3: ~'+ li + li'; 
        @level4: ~'+ li + li + li'; 
        @level5: ~'+ li + li + li + li';
        @level6: ~'+ li + li + li + li + li';    
        &@{first}, 
        &@{withActive}@{first} {
           @{noHover}, @{withHover} {
             background: 1;
           }
        }      
        &@{first} { 
            @{level2}, 
            @{level2}@{withActive} {
              @{noHover}, @{withHover} {
                background: 2;
              }
            }
            @{level3}, 
            @{level3}@{withActive} {
              @{noHover}, @{withHover} {
                background: 3;
              }
            }
            @{level4}, 
            @{level4}@{withActive} {
              @{noHover}, @{withHover} {
                background: 4;
              }
            }
            @{level5}, 
            @{level5}@{withActive} {
              @{noHover}, @{withHover} {
                 background: 5;
              }
            }
            @{level6}, 
            @{level6}@{withActive} {
              @{noHover}, @{withHover} {
                 background: 6;
              }
            }      
            @{withHover} { background: 1h;}
            @{level2} @{withHover} { background: 2h;}
            @{level3} @{withHover} { background: 3h;}
            @{level4} @{withHover} { background: 4h;}
            @{level5} @{withHover} { background: 5h;}
            @{level6} @{withHover} { background: 6h;}
        }
    }
}

CSS Output

ul li:first-child a,
ul li.active:first-child a,
ul li:first-child a:hover, /* <-- Over written */
ul li.active:first-child a:hover {
  background: 1;
}
ul li:first-child + li a,
ul li:first-child + li.active a,
ul li:first-child + li a:hover, /* <-- Over written */
ul li:first-child + li.active a:hover {
  background: 2;
}
ul li:first-child + li + li a,
ul li:first-child + li + li.active a,
ul li:first-child + li + li a:hover, /* <-- Over written */
ul li:first-child + li + li.active a:hover {
  background: 3;
}
ul li:first-child + li + li + li a,
ul li:first-child + li + li + li.active a,
ul li:first-child + li + li + li a:hover, /* <-- Over written */
ul li:first-child + li + li + li.active a:hover {
  background: 4;
}
ul li:first-child + li + li + li + li a,
ul li:first-child + li + li + li + li.active a,
ul li:first-child + li + li + li + li a:hover, /* <-- Over written */
ul li:first-child + li + li + li + li.active a:hover {
  background: 5;
}
ul li:first-child + li + li + li + li + li a,
ul li:first-child + li + li + li + li + li.active a,
ul li:first-child + li + li + li + li + li a:hover, /* <-- Over written */
ul li:first-child + li + li + li + li + li.active a:hover {
  background: 6;
}

/* These over write the third lines of the above output due to the css cascade */
ul li:first-child a:hover {
  background: 1h;
}
ul li:first-child + li a:hover {
  background: 2h;
}
ul li:first-child + li + li a:hover {
  background: 3h;
}
ul li:first-child + li + li + li a:hover {
  background: 4h;
}
ul li:first-child + li + li + li + li a:hover {
  background: 5h;
}
ul li:first-child + li + li + li + li + li a:hover {
  background: 6h;
}

Original Answer Before Mentioning All the Levels

I've cut the code below to just the issue you relate. This can be adapted for the + li code.

Option 1 (very readable)

This (1) keeps the color definition in one place, and (2) groups the two via the comma, but (3) it repeats much selector code, though (4) it is very readable:

ul{
    li{
        &:first-child a, 
        &.active:first-child a:hover {
          background: red;         
        }
        &:first-child a:hover {
          background: blue;
        }
    }
}

Option 2 (code selector once)

This has advantages (1) and (2) from option 1, and overcomes issue (3) by utilizing dynamic selector building with variables (needs LESS 1.3.1+) to make the selector code only input once, however, it could be a little less obvious what is going to produce, and so loses advantage (4) from option 1.

ul {
    li {
        @noActive: ~':first-child a';
        @withActive: ~'.active@{noActive}';
        &@{noActive}, 
        &@{withActive}:hover {
             background: red;
        }
        &@{noActive}{ 
           &:hover { background: blue;}
        }
   }
}

CSS Output for Both

ul li:first-child a,
ul li.active:first-child a:hover {
  background: red;
}
ul li:first-child a:hover {
  background: blue;
}
like image 133
ScottS Avatar answered Oct 27 '22 13:10

ScottS