Extend in Less like it Sass can - less

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 :(

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.

Related

Use LESS to factor out a CSS rule (e.g. font-size: 20px; )

How would you define a CSS style (e.g. font-size: 20px), and reuse it in multiple places with LESS?
According to the LESS docs, I can use variables for keys (e.g. font-size), identifiers (e.g. .myClass), and values (e.g. 20px). However, I'm not seeing an ability to do general rules like this.
Example in SCSS:
Define a mixin
#mixin large-text {
font-size: 20px;
}
Use it elsewhere
.MyAwesomeTitle {
color: red;
#include large-text;
}
Result:
.MyAwesomeTitle {
color: red;
font-size: 20px;
}
Define the mixin. While the leading . makes it look like a class selector, it's just how naming mixins works in LESS.
.large-text() {
font-size: 20px;
}
You include a mixin by just writing the name of the mixin. In this case it's .large-text.
.MyAwesomeTitle {
color: red;
.large-text
}
The docs give an example under "parametric mixins"
Input:
.wrap() {
text-wrap: wrap;
white-space: -moz-pre-wrap;
white-space: pre-wrap;
word-wrap: break-word;
}
pre { .wrap }
Output:
pre {
text-wrap: wrap;
white-space: -moz-pre-wrap;
white-space: pre-wrap;
word-wrap: break-word;
}

Using Less, can I not output a base class for extend?

Using Less, I can not output a mixin class by putting parens after the class name
.my-mixin()
{
color: red;
}
That way it must be used as a mixin and a developer can't accidentally use it as a class like <div class="my-mixin">something</div>.
If I do something similar with extend instead:
.my-base
{
color: red;
}
.my-class:extend(.my-base)
{
background-color: grey;
}
The generated CSS is:
.my-base, .my-class
{
color: red;
}
.my-class
{
background-color: grey;
}
How can I change my Less so that the .my-base class isn't output so that it can't be accidentally used?

Alter LESS Mixin when body class is present?

I have a LESS mixin. When a certain body class is present I want to alter one value of the mixin.
.my-style() {
font-weight: bold;
color: red;
}
.my-style-altered() {
color: blue;
}
.element {
.my-style;
}
.body-class .element {
.my-style-altered;
}
This is working fine. However my list of selectors is getting longer:
.my-style() {
font-weight: bold;
color: red;
}
.my-style-altered() {
color: blue;
}
.element,
.element-2,
.element-3 {
.my-style;
}
.body-class .element,
.body-class .element-2,
.body-class .element-3 {
.my-style-altered;
}
Is there a smarter way of writing my list of selectors so I dont have to repeat them twice? Ideally I would write them once, and for all of them my-style-altered() would be also applied if .body-class is present.
Method 1: (Using different mixins for the base version and the body-class specific version)
Yes, you could avoid having to write all the selectors multiple times by nesting the .body-class * variants of the selector within the generic one and appending the parent selector like in the below snippet. When this code is compiled, Less compiler will automatically replace the & with each one of the parent selectors.
.my-style() {
font-weight: bold;
color: red;
}
.my-style-altered() {
color: blue;
}
.element, .element-2, .element-3 {
.my-style;
.body-class &{
.my-style-altered;
}
}
Compiled CSS:
.element, .element-2, .element-3 {
font-weight: bold;
color: red;
}
.body-class .element,
.body-class .element-2,
.body-class .element-3 {
color: blue;
}
Method 2: (Using same mixin for the base version and the body-class specific version)
Alternately, if you wish to avoid having to use two different mixins and output both the content (the default one and the .body-class * variant) through the same mixin, it can be done like below:
.mixin() {
font-weight: bold;
color: red;
.body-class &{
color: blue;
}
}
.element, .element-2 {
.mixin()
}

Is it possible to nest variables within variables in SASS?

I have a mixin that accepts an argument that I want to pass into a variable.
#mixin my_mixin($arg) {
background-color: $state-#{$arg}-text;
}
Interpolation of variable names is currently not possible in SASS. Here is the issue that discusses.
However, you may use interpolation of placeholders:
%my-dark-styles {
background-color: #000;
}
%my-white-styles {
background-color: #FFF;
}
#mixin my_mixin($arg) {
#extend %my-#{$arg}-styles;
}
.header {
#include my_mixin("dark");
}
.footer {
#include my_mixin("white");
}
This compiles to:
.header {
background-color: #000;
}
.footer {
background-color: #FFF;
}
Since Sass 3.3 you can use maps also https://sass-lang.com/blog/sass-33-is-released
Here is an example:
$state-light-text : #FFFFFF;
$state-dark-text : #000000;
$color-map: ( //create a array to support the two colors light and dark
light: $state-light-text,
dark: $state-dark-text
);
#each $color-key, $color-var in $color-map {
.myclass--#{$color-key} { //will generate .myclass--light .myclass--dark
background-color: $color-var; // equal $state-light-text or $state-dark-text
}
}
It will compile into:
.myclass--light {
background-color: #FFFFFF;
}
.myclass--dark {
background-color: #000000;
}

Less css &:hover

How can I create this class with less?
.class {
display: none;
}
a:hover .class {
display: block;
}
Like this?
.class {
display: none;
a:hover & {
display: block;
}
}
.class {
display: none;
&:hover {
display: block;
}
}
I am assuming from your given CSS code that your HTML structure is like so:
<a>
<div class="class">Content</div>
</a>
You'll be happy to know that what you want to achieve is fairly easy using Less; here's the code shown below:
a {
&:hover {
.class {
//Apply styling here
}
}
}
I hope this helps.