less.js icon indicating copy to clipboard operation
less.js copied to clipboard

Can't extend a nested class (concatenated selector)

Open DennisJohnsen opened this issue 11 years ago • 21 comments

Heya guys.

I have found an annoying issue, which is pretty basic use of two mechanics: I cant extend a class i generate by nesting it using "& {}"

Heres my example:

.box {
    padding: @base-spacing;

    &--large {
        padding: @large-spacing;
    }
}

.foo {
    &:extend(.box--large);
}

Expected result:

.box {
    padding: 24px;
}

.box--large,
.foo {
        padding: 48px;
}

What actually happens:

.box {
    padding: 24px;
}

.box--large {
    padding: 48px;
}

Imo this is very basic use of two mechanics, and it's not like its generated by some kind of wizard looping mixin. Looking forward to have this fixed :-)

Kind regards, Dennis

DennisJohnsen avatar Oct 15 '13 10:10 DennisJohnsen

https://github.com/less/less.js/issues/1539

jonschlinkert avatar Oct 15 '13 11:10 jonschlinkert

https://github.com/less/less.js/issues/1554

jonschlinkert avatar Oct 15 '13 11:10 jonschlinkert

https://github.com/less/less.js/issues/1399

jonschlinkert avatar Oct 15 '13 11:10 jonschlinkert

although closest to #1539 i don't think it is a duplicate.. same root cause as #1539 though..

.a {
   &b

is treated as .a followed by a b element, with no space between them .ab is treated as the class ab.. so less thinks they are different.

quite a hard one to solve, though I guess easier to solve than #1539

lukeapage avatar Oct 15 '13 12:10 lukeapage

fair enough, I guess if solving one doesn't solve the other then it makes sense to keep both open.

jonschlinkert avatar Oct 15 '13 13:10 jonschlinkert

Hello again : - )

I'm just writing to hear if theres some updates regarding this issue.

I have recently forwarded multiple people this issue, regarding to their LESS question about not beeing able to extend nested/generated classes.

Kind regards Dennis

DennisJohnsen avatar Nov 20 '13 09:11 DennisJohnsen

+1

I tried doing the exact same thing:

.top{
    &-first{
        background:black;
        &-item{
            color:white;
        }
    }
    &-second{
        background:green;
        &-item:extend(.top-first-item){}
    }
}

expecting:

.top-first {
    background: black;
}
.top-first-item,
.top-second-item{
    color: white;
}
.top-second {
    background: green;
}

But got instead:

.top-first {
    background: black;
}
.top-first-item{
    color: white;
}
.top-second {
    background: green;
}

Soo +1 for this issue and looking forward to a fix! :)

Original: http://stackoverflow.com/questions/20091264/less-extend-a-previously-defined-nested-selector

Johns3n avatar Nov 20 '13 10:11 Johns3n

A lot of people are into BEM these days...

.block {
  &__elem {
    width: 200;
  }

  &__elem_mod_blue {
    &:extend(.block__elem);
    color: blue;
  }

  &__elem_mod_green {
    &:extend(.block__elem);
    color: green;
  }
}

dvdln avatar Dec 21 '13 04:12 dvdln

I guess the easiest way to fix is in the code handling & to change it to combine the value if there are no combinators between the previous value and the next value, then this would work. patches welcome!

lukeapage avatar Dec 21 '13 09:12 lukeapage

Hello again.

Any updates into this? I havn't been following it for some time, but i find my self not beeing able to extend these dynamic classes a abit too often :(

Kind regards, Dennis

DennisJohnsen avatar May 17 '14 22:05 DennisJohnsen

Again a +1 from me! Found myself needing to be able to extend a nested dynamic class the other day :)

.ui{
    &__theme{
        background-image:url(../images/watermark.gif);
        background-position:top left;
        background-attachment:fixed;
        background-repeat:no-repeat;
        &--inverted{
            &:extend(.ui__theme);
            background-image:url(../images/watermark--inverted.gif);
            background-position:top right;
        }
    }

expected:

ui__theme, ui__theme--inverted{
   //shared rules
}
ui__theme--inverted{
 //individual
}

Johns3n avatar May 20 '14 06:05 Johns3n

I've been working on the singlepage project, where each page has it's own less file compiled. Each page has it's own body class, so I can extend concatanated classes and other properties like so: Let the pages have classes:

<body class="foo-bar-page">
<body class="bar-baz-page">

In my less files i start from not existing classes

.foo-bar {
  &-page {
    min-height:100%;
    #somediv {
      color : red;
    }
    &-holder {
      display : inline-block;
    }
  }  
}

For the other page i can just write:

.bar-baz {
  &:extend(.foo-bar all);
}

And the output will be:

.foo-bar-page,
.bar-baz-page {
  min-height: 100%;
}
.foo-bar-page #somediv,
.bar-baz-page #somediv {
  color: red;
}
.foo-bar-page-holder,
.bar-baz-page-holder {
  display: inline-block;
}

Sure if you need to inherit everything. Less 1.7.0

slantz avatar Jul 18 '14 13:07 slantz

+1!

jaredly avatar Aug 21 '14 20:08 jaredly

Merging to #2200.

seven-phases-max avatar Sep 18 '14 18:09 seven-phases-max

Hello, I know it's now into https://github.com/less/less.js/issues/2200 BUT 5 years without solution is it outdated ??

guillaume-duchemin avatar Sep 18 '18 14:09 guillaume-duchemin

@guillaume-duchemin Not out-dated. Marked as up-for-grabs, so anyone can submit a PR for it at anytime.

matthew-dean avatar Sep 18 '18 17:09 matthew-dean

+1

rejhgadellaa avatar Jul 24 '19 20:07 rejhgadellaa

+1

kubami19 avatar Jul 31 '19 11:07 kubami19

+1

acjbizar avatar Aug 14 '19 11:08 acjbizar

In case someone comes here with a case like @Johns3n's example, you can always just convert that to the following to "share" rules between BEM classes:

.ui {
    &__theme {
        background-image:url(../images/watermark.gif);
        background-position:top left;
        &, &--inverted {
            background-attachment:fixed;
            background-repeat:no-repeat;
        }
        &--inverted {
            background-image:url(../images/watermark--inverted.gif);
            background-position:top right;
        }
    }
}

i.e. the key useful "trick" in Less is the &, &[something] { pattern, where you can abstract common rules without using "extend"

matthew-dean avatar Sep 19 '19 19:09 matthew-dean

This would be a great feature as utility classes become even more popular. I was wanting to remove some utility classes from the markup where the sizing was set in stone. It would've been nice to just drop in &:extend(.padding-left-small); or &:extend(.padding-all-medium-lg-up);. I suppose I could wrap it in a mixin or something? Still, that's not intuitive when we have extends. Thanks for all the work you devs have done, though!

.padding {
  &-left {
    &-small {
        padding-left: @gutter-small !important;
    }
    &-...
  }
  &-...
}

kerryj89 avatar Apr 16 '20 02:04 kerryj89