How to call LESS Mixins outside of CSS Classes? - less

Although LESS is a Preprocessor, how can I do this
#ltr: ltr;
#rtl: rtl;
#dir: #rtl;
.SetTypeFaceVariables when (#dir = #ltr) {
#headType: 'Segoe UI_';
}
.SetTypeFaceVariables when (#dir = #rtl) {
#headType: Tahoma;
}
.SetTypeFaceVariables(); // Error is here, we cannot call Mixins here like this
h1{
font-family: #headType;
}
How can I define #headType variable in different direction?
Thanks to #seven-phases-max you can find the Demo on Codepen

As it's already mentioned in comments your example compiles fine with Less version 1.5.0 and higher. Most likely your IDE ships with some outdated version of the Less compiler (1.4.2? 1.3.3?). Never mind, you need just a tiny fix to make the code to be compatible with ancient Less versions (down to 1.3.2):
#ltr: ltr;
#rtl: rtl;
#dir: #ltr;
// the magic is in parens:
.SetTypeFaceVariables() when (#dir = #ltr) {
#headType: 'Segoe UI_';
}
.SetTypeFaceVariables() when (#dir = #rtl) {
#headType: Tahoma;
}
.SetTypeFaceVariables();
h1 {
font-family: #headType;
}

Related

Using mixins as functions

I need to return value form LESS Mixin to less CSS attribute. It is simple in SCSS but unable to replicate it in Less. Anyone who can resolve this issue for me. Thanks in advance. Below is the example what I wanted to achieve form LESS Mixin.
In LESS
.rem(#pixel) {
#em: unit(#pixel*0.025,rem);
}
Not able to return this value like in SCSS
In SCSS
#function pxtorem($pixels, $context: 0.0625) {
#return #{$pixels*$context}rem;
}
.div {
font-size: rem(16);
}
output:
.div {
font-size: 1rem;
}
Want to return the value like in SCSS
See Using Mixins as Functions.
I.e. in your case it will be something like:
.pxtorem(#pixels, #context: 1./16) {
return: 1rem * #pixels * #context;
}
.div {
font-size: .pxtorem(8)[];
}

Declare variable in sass for color web changer [duplicate]

This question already has an answer here:
Define variables in Sass based on classes
(1 answer)
Closed 6 years ago.
i am making color changer for my web, is it possible to make variable like this :
.red { $color: red; $background: red; }
.green { $color: green; $background: green; }
.blue { $color: blue; $background: blue; }
thanks
There's nothing inherently wrong with your SASS here - at least in principle - but syntatically it's a tad skewed. Also, what your trying to do though requires so client side run-time code for it to be implemented.
First up though you don't actually need the variables - but we'll run with it. So change your sass to
$red: #ff1a1a;
$green: #5cd65c;
$blue: #1a75ff;
.blue { background-color: $blue; }
.green { background-color: $green }
.red { background-color: $red }
assuming this generates a CSS file and your importing this into your HTML page you'll need a little bit of Javascript to apply the appropriate colour class to the element you want to take on this property.
Assuming you have 3 elements ( buttons ) with unique ID's, which when clicked will change the background colour of an element id=foo you could have something like
var changeColor = function(col) {
document.getElementById("foo").className = col
}
document.getElementById('buttonblue').addEventListener('click',
function() {
changeColor('blue');
}, false);
document.getElementById('buttongreen').addEventListener('click',
function() {
changeColor('green');
}, false);
// ... etc etc for each color button you have
This is far from clean or modularised code, but hopefully it outlines the principle of the process which you need to follow
Here's a working codePen with the example: http://codepen.io/anon/pen/rewoOY

How do i check if a variable is set or not in Less like Sass's variable_exists($name)

I am trying to convert Sass to Less but I got problem. In Sass code there are variable_exists($name) but Less does not have similar function. So I converted code below
Sass
.test {
background: if(variable-exists(background), $small-font-size, red);
}
↓
Less
.define-test(#background: red) {
background: #background;
}
.test {
.define-test();
}
It works but I got problem if it will be complicated code. Please tell me how to convert complicated Sass code in Less below:
Sass
.test {
font: if(variable-exists(font-size), $font-size, 100%)/#{if(variable-exists(line-height), $line-height, 1.5)};
}
Thanks in advance.
Don't:
While it's possible to convert this code line-by-line (using some hints from #1894 and #1400), like this for example:
// defaults:
#font-size: none;
#line-height: none;
// styles:
.test {
.-(#s, #h) {#size: #s; #height: #h}
.-(none, #h) {#size: #s}
.-(#s, none) {#height: #h}
.-(#font-size, #line-height);
font: #font-size/#line-height;
}
// user/custom overrides (comment/uncomment to test):
#font-size: 33px;
#line-height: 5.55;
Demo.
Do:
You actually don't need any of above conditionals at all if you go a declarative way. The right Less code for that stuff is as simple as this:
// defaults:
#font-size: 100%;
#line-height: 1.5;
// styles:
.test {
font: #font-size/#line-height;
}
// user/custom overrides (comment/uncomment to test):
#font-size: 33px;
#line-height: 5.55;
Demo.
Note that neither of these "config" variables have to be global. You can use namespaced variables to override both global defaults (like this) or also namespaced defaults (like this), and so on.

LESS Variable Interpolation

I'm trying to simplify my CSS even further than I already have with LESS by using functions and variable interpolation. I was completely unaware of variable interpolation until I took a look at Hover.css' less files which is no surprise as to why I'm screwing up now.
I'm working on Reddit to make a flair system and I am encountering problems using variable interpolation.
I am currently using the below as a test:
.flair.flair-one { color: red; }
.flair.flair-two { color: green; }
.flair.flair-three { color: blue; }
.custom(#a; #b; #c) {
&::before { .flair.flair-#{a}; }
.flair.flair-#{b};
&::after { .flair.flair-#{c}; }
}
.this-flair {
.custom(one; two; three);
}
That's the basic structure of what I'm doing. While testing in online compilers, .this-flair isn't working.
Is someone able to tell me what I can do to resolve this? I'm looking through the LESS functions and it appears as though this is the correct way to do it.
As mentioned in comments above you can't interpolate either mixin or function calls. In a quick glance, parametric mixins (with pattern matching) are what you actually need to use for such snippets:
.flair-flair(one) {color: red}
.flair-flair(two) {color: green}
.flair-flair(three) {color: blue}
.custom(#a, #b, #c) {
.flair-flair(#b);
&::before {.flair-flair(#a)}
&::after {.flair-flair(#c)}
}
.this-flair {
.custom(one, two, three);
}

Is there any (good) way to extend a class within a mixin, and then use that mixin within a media query, using Less?

I've been working on building out some Less files to help speed up my CSS workflow, and also to help produce more efficient, cleaner CSS.
The way I see it:
Mixins are a great way to help speed up the workflow, but they have the drawback of potentially making the outputted CSS longer than necessary.
Extending classes is the ideal solution for ensuring the amount of duplicate style declarations is minimized, helping clean that up...
So, to help balance things out I wrote out a set of standard, commonly used styles, using dummy classes (they are stored in a file which is imported by reference, so the styles are only output if they get extended).
I set all of my Mixins to extend these classes wherever possible, which worked great for the most part.
However, I realized my pitfall once I got to my media queries... I can't extend those classes within the media query, which would be fine normally, I would just remember not to do so.. But since the Mixins also now use my extends, I can now no longer use them inside media queries either.
I'm not willing to avoid using the Mixins inside of the media queries because of this, but I'd really love to be able to find a way to keep extending classes within them to keep my output as clean as possible.
The only idea I've thought of so far is to add an extra parameter to every Mixin to specify wether it should extend or not, but that's less than ideal.
My hope is that someone can come up with a much more clever solution, that would allow me to maintain the benefit of Mixins which extend base style classes, but also maintain easy usability, without over complicating things. Might be a tall order, but here's hoping.
In case my explanation was hard to follow, this is what I would have hoped to be able to do, but is not currently possible:
Ideal Input
// extensions.less
.block {
display: block;
}
// mixins.less
#import (reference) "extensions";
.mixin {
&:extend(.block);
margin: auto;
}
// styles.less
#import "mixins";
.element1 {
.mixin();
}
.element2 {
.mixin();
}
#media only screen and (max-width: 768px) {
.element3 {
.mixin();
}
.element4 {
.mixin();
}
}
Ideal Output
// styles.css
.element1, .element2 {
display: block;
}
.element1 {
margin: auto;
}
.element2 {
margin: auto;
}
#media only screen and (max-width: 768px) {
.element3, .element4 {
display: block;
}
.element3 {
margin: auto;
}
.element4 {
margin: auto;
}
}
In short, yes, currently it is somewhat possible but requires some additional wrapping for a top level classes:
// extensions.less
.block {
display: block;
}
// mixins.less
#import (reference) "extensions";
.mixin() {
&:extend(.block);
margin: auto;
}
// styles.less
#media all { // !
#import "mixins";
.element1 {
.mixin();
}
.element2 {
.mixin();
}
}
#media only screen and (max-width: 768px) {
#import (multiple) "mixins";
.element3 {
.mixin();
}
.element4 {
.mixin();
}
}
.element1 and .element2 (and any other class to extend .block) have to be put into #media all because currently:
Top level extend matches everything including selectors inside nested media
So if .element1 and .element2 stay in the global scope they leak into every other #media .block declaration.
(Hmm, actually for me this "top level extend matches everything" thing looks questionable and contradicts another "extend inside a media declaration should match only selectors inside the same media declaration" rule (obviously because global scope = #media all thus they should work identically)).