I have a SASS variable like the following:
$surrounding-margin: 0 40px;
And I'm using it like this (the irrelevant properties have been removed):
#content {
margin: $surrounding-margin;
& #close {
margin-right: -$surrounding-margin[1]; // If this was JS.
}
}
Obviously, -$surrounding-margin[1] won't work. What will? I need the second value of the variable, in the negative. How can I do this?
Just use for example nth because it's just a list:
$surrounding-margin: 0 40px;
#content {
margin: $surrounding-margin;
& #close {
margin-right: -(nth($surrounding-margin, 2));
}
}
Related
I have the following SCSS code:
#appMain {
margin-right: 25em + 1em;
}
#appLeft {
float: left;
width: 100%;
padding-left: 1em;
}
#appRight {
float: right;
width: 25em;
margin-right: -25em - 1em;
}
Now I want to use parameters, so I created 2 variables
$rightDimension: "25em";
$marginBetween: "1em";
When I change the code this way
#appMain {
margin-right: $rightDimension + $marginBetween;
}
Instead of getting 26em, I now get 25em1em resulting in invalid css and thus, the property doesn't apply.
What am I doing wrong? How can I do this simple math with SASS?
Since you quoted the values, Sass treats them as strings rather than values and does a concatenation instead of an addition (like Javascript would do it as well).
Simply omit the quotes to make it work.
$rightDimension: 25em;
$marginBetween: 1em;
working example
I'm trying to combine one ruleset into two different rulesets with variable values swapped. Main purpose is LTR/RTL internationalization.
Usage:
h1 {
margin-top: 10px;
.directions({
margin-#{left}: 5px;
});
}
Expected output:
h1 {
margin-top: 10px;
}
.ltr h1 {
margin-left: 5px;
}
.rtl h1 {
margin-right: 5px;
}
I was able to get some results with the Passing Rulesets to Mixins function available in Less 1.7
.directions(#rules) {
#left: left;
.ltr & { #rules(); }
#left: right;
.rtl & { #rules(); }
}
The problem is that the #left variable is always set to the last value used in .directions() mixin (right in this case). Is there any way how to swap variable or pass it back outside of the mixin?
Note: I do not want to output LTR/RTL to two separate files, I'm trying to combine them into one file.
To understand Less variables scope and life-time see:
Lazy Evaluation (aka Lazy Loading).
Variable Semantics
Most Misunderstood
Scope
Last Declaration Wins
The solution for your particular case is as simple as:
.directions(#styles) {
.ltr & {
#left: left;
#styles();
}
.rtl & {
#left: right;
#styles();
}
}
H i,
Hoping you can help.
Is there a way for LESS to return just a value - feel like I'm missing something very obvious
Say I have:
#unit:em;
#basevalue:1;
Can I use something to give me a shorthand return for -
.someClass { padding: ~'#{basevalue}#{unit}'; }
Like say:
.returnUnit() { ~'#{basevalue}#{unit}'; }
.someClass { padding: returnUnit(); }
because what I'm ultimately hoping for is:
.returnUnit(#val) { #basevalue*#val#{unit}; }
.someClass { padding:returnUnit(0.5); }
Using a mixing I have to define the style property, however the value of this return function would be used for many different css properties.
Hope I made sense and I am just lacking deeper rtfm.
Many Thanks if you can.
Update as #Chococrocs pointer to the docs, thanks.
.average(#x, #y) {
#average: ((#x + #y) / 2);
}
div {
.average(16px, 50px); // "call" the mixin
padding: #average; // use its "return" value
}
Looks like what I need ? - just seeing if I can always tag on the unit variable to it....
Update: That gets part way ...
.unitRelative(#val) {
#value : #basevalue*#val;
#relative: ~'#{value}#{unit}';
}
/* usage */
.someClass {
.unitRelative(2);
padding: #relative;
}
But not when
.someClass {
.unitRelative(2);
padding:#relative;
.unitRelative(3);
margin:#relative;
}
Is there another way ?
LESS has no way as of yet to create a true "function," so we cope with it.
First
You can just use the unit function, like so:
LESS
.someClass { padding: unit(#basevalue, #unit); }
.someOtherClass { padding: unit(#basevalue*0.5, #unit); }
CSS
.someClass {
padding: 1em;
}
.someOtherClass {
padding: 0.5em;
}
Second
The mixins as functions is okay in some situations, but as you discovered, has the limitation of only setting the value once on the first call (and that is assuming a variable of the same name does not exist in that scope already).
LESS (first works right, second doesn't)
.returnUnit(#val:1) {
#return: unit(#basevalue*#val, #unit);
}
.someThirdClass {
.returnUnit(0.4);
padding: #return;
}
.someOoopsClass {
.returnUnit(0.4);
padding: #return;
.returnUnit(0.3);
margin: #return;
}
CSS Output
.someThirdClass {
padding: 0.4em;
}
.someOoopsClass {
padding: 0.4em;
margin: 0.4em; /* Ooops! Not 0.3em! */
}
Third
Limitation of the Second idea can be avoided by a second wrapping, as it isolates the scope for each variable returned by .returnUnit(), like so:
LESS
.someAccurateClass {
& {
.returnUnit(0.4);
padding: #return;
}
& {
.returnUnit(0.3);
margin: #return;
}
}
CSS Output
.someAccurateClass {
padding: 0.4em;
margin: 0.3em; /* Yes! */
}
Fourth
It may be better to merge ideas from the First and Third by adding some global variables and doing this:
LESS
#unit:em;
#basevalue:1;
#val: 1;
#setUnit: unit(#basevalue*#val, #unit);
.someAwesomeClass {
& {
#val: .2;
padding: #setUnit;
}
& {
#val: .1;
margin: #setUnit;
}
}
CSS Output
.someAwesomeClass {
padding: 0.2em;
margin: 0.1em;
}
So here we are using the unit function still as the First idea, but have assigned it to the variable #setUnit, so each time the variable is called, it runs the function. We still isolate our property blocks using the & {} syntax like in the Third solution, but now we just set the #val to what we want and call the #setUnit where we want.
There is a hack that is mentioned here by fabienevain using a global js function. Seems to be good option if you want a function with actual return value.
#fn: ~`fn = function(a) { return a; }`;
#arg: 8px;
p {
font-size: ~`fn("#{arg}")`;
}
I think you look for this, Mixin as a function
http://lesscss.org/features/#mixins-as-functions-feature
Reading your question, I think is what you're wishing, ;D
// mixin
.parseInt(#string) {
#parseInt: unit(#string, );
}
Usage:
.selector {
.parseInt(100px);
width: #parseInt + 10; // px will automatically be appended
}
Result:
.selector {
width: 110px;
}
one of the simplest work around would be to pass the property and the value.
mixin.less
.lighter(#property, #color) {
#{property}: multiply(white, fade(#color, 10%));
}
use.less
.my-class{
.lighter(background-color, #FF0000);
}
Results:
.my-class{
background-color: #fbe8eb;
}
Is there an efficient way to write the sass to have a css output like below where I have a native <p> tag without a class and then have classes for the <p> tag?
SASS
article {
.main {
p {
margin: 0 auto;
width: 54.717%;
}
p.pull-graph {
margin-bottom: 1em;
}
}
}
CSS
article.main p.pull-graph {
margin-bottom: 1em;
}
article.main p {
margin: 0 auto;
width: 54.717%;
}
you could avoid to repeat the tagname p for every class using the & reference to the parent selector
article {
.main {
p {
margin: 0 auto;
width: 54.717%;
&.pull-graph {
margin-bottom: 1em;
}
}
}
}
As a side note, also consider to mantain your css rules as short as possible (so as to reduce the specificity of your selectors)
E.g. as a small improvement, you could set role="main" to the article and use [role="main"] p (specificity 11) instead of article.main p (spec. 12).
Another better improvement could be using HTML5 <main> element in place of article.main and your selector becomes main p (spec. 2)
In less.js, I'm able to replace values with variables with no problems.
#gutter: 20px;
margin-left:e(%("-%d"), #gutter);
When trying to replace properties with variables, I get errors. How would I perform the following in Less?
#gutter: 20px;
#direction: left;
e(%("margin-%d"), #direction):e(%("-%d"), #gutter);
Thanks to Alvivi for the solution and research (you get the reward for that). I decided to add the following as the actual answer since this is a real way to set it up instead of looking at .blah() pseudo code..
Here's a real strategy for setting it up:
#gutter: 20px;
#dir: left;
#dirOp: right;
then create mixins to enhance margin and padding like so:
.margin(left, #dist:#gutter) {
margin-left:#dist;
}
.margin(right, #dist:#gutter) {
margin-right:#dist;
}
.padding(left, #dist:#gutter) {
padding-left:#dist;
}
.padding(right, #dist:#gutter) {
padding-right:#dist;
}
.lr(left, #dist: 0) {
left: #dist;
}
.lr(right, #dist: 0) {
right: #dist;
}
.. then you can just
#selector {
.margin(#dir);
}
or
#selector {
.margin(#dirOp, 10px);
}
all together:
#selector {
.margin(#dir);
.margin(#dirOp, 50px);
.padding(#dir, 10px);
.padding(#dirOp);
float:#dir;
text-align:#dirOp;
position:absolute;
.lr(#dir);
}
Easy breezy LTR/RTL with LESS! Woot!
Escaping, as says the documentation, is used to create CSS values (not properties).
There is a discussion with some workarounds here. One would be using parametric mixins. For example:
.g () { /* Common properties */ }
.g (right) { margin-right: e(...) }
.g (left) { margin-left: e(...) }