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);
}
Related
I crated many mixins to generate different kinds of classes for various purposes. Specifically I have to use a unique colorizer set using the standard bootstrap variable name, such as (only an example):
#type-primary: #fff;
#type-success: #f00;
#type-info: #ff0;
#type-default: #000;
#type-warning: #0f0;
#type-danger: #0ff;
Actually I created my mixins in the following form, with a "mother" as prefix to which I attached various suffixes
.text
{
&-primary { .color_text(#type-primary); }
&-success { .color_text(#type-success); }
&-info { .color_text(#type-info); }
&-default { .color_text(#type-default); }
&-warning { .color_text(#type-warning); }
&-danger { .color_text(#type-danger); }
}
After this, I can then create the final called mixin such as (so simple because it's only an example)
.color_text (#color)
{
color:#color;
}
I woud like to automate and optimize .text mixin to avoid many repeated rows, I think with a for loop. How could be possible?
Final results should be (in this case)
.text-primary {
color: #fff;
}
.text-success {
color: #f00;
}
.text-info {
color: #ff0;
}
.text-default {
color: #000;
}
.text-warning {
color: #0f0;
}
.text-danger {
color: #0ff;
}
In PSEUDO-CODE something like this could be ideal
#type-primary: #fff;
#type-success: #f00;
#type-info: #ff0;
.createContextClass("classNamePrefix",{#type-primary,#type-success,#type-info},mixinToBeCalled);
// Another call could be
.createContextClass("otherClassNamePrefix",{#type-primary,#type-success},otherMixinToBeCalled);
where, in relation to my original code, classNamePrefix should be the name of first part of final CSS class, then is passed an array with all kind of suffix that I wish in final CSS code, and mixinToBeCalled is the mixin that creates all css rules for final .text-primary, .text-success, .text-info.
For the moment, following Seven-Phases-Max' suggestion, I improved his solution in the following way
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
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.
I have this very simple example as you can see:
.large{
color: blue;
}
.a(#va){
.large;
~".#{va}()";
}
a{
.a(large)
}
I keep trying to get the .large() or .large; to work by calling the .large mixin. I keep getting error:
Parse error: Unrecognised input
.large; ~".#{va}()";}
How can I fix this?
You can't call a mixin by its name stored in a variable. You can achieve the goal by wrapping mixin call into "detached ruleset" though, e.g.:
.large {
color: blue;
}
.a(#va) {
#va();
}
a {
.a({.large})
}
There're other methods of doing similar things (might be more useful/suitable depending on a use-case).
I'm using LESS to build a site, and want the layout to switch based on direction, either 'ltr' or 'rtl' (direction:rtl)
I set #direction at the top. Then there are certain elements that I want floated left for ltr, and right for rtl. I also want to position absolute, and apply padding-left/right based on the #direction.
Instead of writing out separate mixins for float, pos and padding, I was trying to do something like this:
.mixin (#direction) when (#direction = ltr) {
#lr:left;
}
.mixin (#direction) when (#direction = rtl) {
#lr:right;
}
Then call it like this:
ol li {
float:#lr;
}
and/or
ol li span.date {
position:absolute;
#lr:0;
}
That's the idea, but any help would be appreciated. I've looked at guards, and parametric mixins but just can't seem to nail it.
I have an idea for your case which solve RTL problem. In each class, we define 2 mixin within it for direction stylesheet properties. The prototype like that:
// #direction variable should be put by somehow
#direction: rlt;
.foo {
// common properties;
.dir(#direction);
.dir(rtl) {
// RTL properties;
}
.dir(ltr) {
// LTR properties;
}
}
For example:
// #direction variable should be put by somehow
#direction: rlt;
.foo {
color: #000000;
.dir(#direction);
.dir(rtl) {
float: left;
padding-left: 5px;
background: "rtl.png";
}
.dir(ltr) {
float: right;
padding-right: 5px;
background: "ltr.png";
}
}
OK. After some playing and a bit of thinking this is what I've come up with. If I can't use variables as properties then I'll use #direction, and #directionOpp (opposite of rtl, ltr) to use as a layout helper.
I have 2 variables.
#direction: ltr; // Change to 'rtl' for arabic, hebrew, etc.
#directionOpp: rtl; // Make this opposite of #direction, for easier mixins
Here's my mixin for horizontal positioning.
#dir {
.dir(ltr,#dist:0) {left: #dist;}
.dir(rtl,#dist:0) {right: #dist;}
.float(ltr){float:left; }
.float(rtl){float:right;}
.margin(ltr, #dist:#a){margin-left:#dist;}
.margin(rtl, #dist:#a){margin-right:#dist;}
.padding(ltr, #dist:#a){padding-left:#dist;}
.padding(rtl, #dist:#a){padding-right:#dist;}
}
and here's how I call it.
ol li {
#dir.float(#direction);
#dir.padding(#direction);
}
If I ever need to reverse anything, then I can replace #direction with #directionOpp.
I can also specifiy how much #dist I need as it's parametric mixin, and since they're all separate I can have any combination of margin, float, padding etc I need without multiple mixins with hard coded properties.
Good solution?
Dave
Your first issue is that variables are actually constants in LESS. So once you set it, it can not be overwritten. When you set #lr to "left", then it will always have "left" as its value, even if you try to reset the variable. Which is the issue with your first idea.
As far as your second idea, LESS does not support using variables as properties, only values. However you can hack around it like so:
.mixin(#prop, #value) {
Ignore: ~"a;#{prop}:#{value}";
}
This isn't very clean, but it does the trick if you absolutely need the functionality. Word is it is in the works for 1.4.
Also, you are calling the mixin incorrectly. Try something like this:
.mixin (#direction) when (#direction = ltr) {
float: left;
}
.mixin (#direction) when (#direction = rtl) {
float: right;
}
Then call it like this:
ol li {
.mixin(ltr);
}
Which should spit this out:
ol li {
float: left;
}
Try this Mixins in your LESS files
#rtl: rtl;
#ltr: ltr;
#direction: #rtl;
then Use them like this
html {
direction: #direction;
}
body{
direction: #direction;
}
for Left and Right commands you should use these mixins
.DockItem(#location, #value) when (#location = "left") and (#direction = #ltr){
left: #value;
}
.DockItem(#location, #value) when (#location = "right") and (#direction = #ltr){
right: #value;
}
.DockItem(#location, #value) when (#location = "left") and (#direction = #rtl){
right: #value;
}
.DockItem(#location, #value) when (#location = "right") and (#direction = #rtl){
left: #value;
}
then in your less file you should call this mixins like this
.TestClass{
.DockItem('left', '100%');
}
Note that I set #direction to RTL so above style would result like this
.TestClass{
right: 100%;
}
If you set chnage the directionality of the page to LTR it would result like this
.TestClass{
left: 100%;
}
Let me know if it helps you or not
I implemented a rtl extension in dotless. Find it on github. That extension reverwses float:left to float:right and margin-left:5px to margin-right:5px.
It also supports prefixing properties to control how they are reversed.
A lot more info is available on the dotless wiki for the plugin.
You can find generic information on how to use dotless and plugins also on the wiki.