Extend in Less like it Sass can

I like to use :extend() in Less like I can do it in Sass.

Example in SCSS: http://codepen.io/Grawl/pen/qEeQPG

Example in Less: http://codepen.io/Grawl/pen/qEeQpz (not worked)

Expected output:

.datalist-item {
  display: block;
}
.datalist-item-term {
  font-weight: normal;
}
.datalist-item-description {
  font-weight: bold;
}
.datalist-float .datalist-item {
  display: inline-block;
}
.datalist-float .datalist-item:not(:last-of-type) {
  margin-right: 1em;
  padding-right: 1em;
  border-right: 1px solid;
}

The purpose is to not self-repeat, so if I rename one class in Sass I have not to rename others.

I know I can put root class in a variable and use it twice with it http://codepen.io/Grawl/pen/qEeQpz but it looks ugly :(

Upvotes: 4

Views: 1481

Answers (1)

Bass Jobsen
Bass Jobsen

Reputation: 49044

Your Sass (SCSS) example uses @extend-Only Selectors which is some special form of extending which does not exists in Less.

Firstly a "normal" extend:

SCSS:

.class {
p: 1;
}
.class2 {
@extend .class;
}

and Less:

.class {
p: 1;
}
.class2 {
&:extend(.class);
}

both compile into:

.class,
.class2 {
  p: 1;
}

In Less .class2 { &:extend(.class); } can also be written as .class2:extend(.class1){}

Now consider the following SCSS code which uses @extend-Only Selectors:

%class {
 p: 1;
}

.class2 {
@extend %class;
}

The preceding code compile into CSS code as follows:

.class2 {
   p: 1; }

Sass documentation tells you:

@extend-Only Selectors

Sometimes you’ll write styles for a class that you only ever want to @extend, and never want to use directly in your HTML. This is especially true when writing a Sass library, where you may provide styles for users to @extend if they need and ignore if they don’t.

If you use normal classes for this, you end up creating a lot of extra CSS when the stylesheets are generated, and run the risk of colliding with other classes that are being used in the HTML. That’s why Sass supports “placeholder selectors” (for example, %foo).

Placeholder selectors look like class and id selectors, except the # or . is replaced by %. They can be used anywhere a class or id could, and on their own they prevent rulesets from being rendered to CSS.

In Less you will have two options to have code that does not generate output:

1) use a mixin, mixins do not generate output:

.class() {
p: 1;
}
.class2 {
.class();
}

outputs:

.class2 {
   p: 1; 
}

2) put your classes which should not output in a different file and import this file with the reference kewyword:

file1.less:

.class {
p: 1;
}

file2.less:

@import (reference) "file1";
.class2 {
&:extend(.class);
}

lessc file2.less will output now:

.class2 {
   p: 1; 
}

But i agree with @seven-phases-max in the comments in the first place. In your example there is no need to use extend. @seven-phases-max shows you some examples to solve this use case. Alternatively you can consider; changing selector order with parent reference, which should work in both Less and SASS:

.datalist-item {
  display: block;

  &-term {
  font-weight: normal;
  }

  &-description {
  font-weight: bold;
  }

  .datalist-float & {
  display: inline-block;

      &:not(:last-of-type) {
      margin-right: 1em;
      padding-right: 1em;
      border-right: 1px solid;
      }  

  }

}

Compile into:

.datalist-item {
  display: block;
}
.datalist-item-term {
  font-weight: normal;
}
.datalist-item-description {
  font-weight: bold;
}
.datalist-float .datalist-item {
  display: inline-block;
}
.datalist-float .datalist-item:not(:last-of-type) {
  margin-right: 1em;
  padding-right: 1em;
  border-right: 1px solid;
}

Finally notice that you are using nesting of properties such as:

 border: {
     right: 1px solid;
 };

which should compile into:

border-right { 
1px solid; 
}

Less does NOT support nesting of properties.

Upvotes: 6

Related Questions