How to add/sub to a dynamic variable? - css

I have a problem with the following code:
#viewport-large: 1440px;
#viewport-medium: 1366px;
#viewport-small: 1280px;
#type: medium;
#setting: ~"#{viewport-#{type}}";
#value: (#setting + 1); // here can't add 1
It will show an error message in the LESS compiler saying: "Operation on an invalid type".
Can anyone tell me why this is the case? What should I do?

The output of Less' CSS escape function (e() or ~"") is a string and you can't add a number to it. This is why the compiler reports Operation on invalid type.
So, instead of doing it that way make use of the double resolution (##) like in the below code block:
#viewport-large: 1440px;
#viewport-medium: 1366px;
#viewport-small: 1280px;
#type: medium;
#setting: "viewport-#{type}"; /* this won't resolve into 1336px as yet */
#value: ##setting + 1px; /* resolution to 1336px + addition happens here */
In this method, we just form the variable name and set it to the #setting variable (instead of setting a actual px value) and so the real px value's type remains unpolluted. In the next line when we use the double #, Less compiler would try to fetch the value that is held by the variable whose name is same as the value of #setting variable and immediately sum 1px to it instead of converting it to a String.
Note: If you have the Strict Math option (--strict-math) enabled then the addition operation must be wrapped inside extra braces like below. Else, it would plainly output a concatenated value like 1366px + 1px instead of performing the addition and outputting 1367px.
#value: (##setting + 1px);
The --strict-math setting is disabled by default but some of your projects could have enabled it.

Related

Stylus: how to create a CSS variable with a Mixin interpolation

How can a Stylus Mixin interpolate for both sides of the definition of a variable, such as:
--MyVariable: MyVariable
In the compiled CSS, --MyVariable should remain as the variable name, whereas the second variable should be the numerical value computed for this Stylus variable defined elsewhere.
I will have many such pairs of a CSS variable and a Stylus variable. Now, even though I could just manually write them down in the Stylus file, I would like to have a Mixin that allows me to create them by writing the shared part of the names just once as the Mixin's single argument, such as:
VariablePair(MyVariable-1) // --MyVariable-1: MyVariable-1
VariablePair(MyVariable-2) // --MyVariable-2: MyVariable-2
VariablePair(MyVariable-3) // --MyVariable-3: MyVariable-3
I tried:
VariablePair(VariableName)
--{VariableName}: VariableName
VariablePair(MyVariable)
It didn't parse.
I realized that MyVariable without '' would come as an actual value that couldn't be affixed to --. But, adding '' to it as VariablePair('MyVariable') would result in the right side of the definition itself becoming a string instead of the Stylus variable for computation.
I tried the different combinations of the presence/lack of the brackets and '' and $ as well as concatenations, but none of them seem to work. '--' + VariableName + ': ' + VariableName (with/without the brackets/$) isn't working, it either doesn't parse or does parse but without creating a line in the compiled CSS.
Is there a solution to this?
unquote works for this:
VariablePair(name, val)
{unquote('--' + name)}: val
.selector
VariablePair('fontcolor', red)
color: var(--fontcolor)
will output
.selector {
--fontcolor: #f00;
color: var(--fontcolor);
}

Is there a way to print SASS value to output?

Suppose we have:-
$value: 13.37;
$length: $value + 0em;
Now i wanted to check the value of $length.
Is there anything similar to Javascript's Console.log?
If you want it to appear on the page itself, I believe you could attach it as the value of a pseudo-element. Something like:
body::before{ content: "#{$length}"}
Additionally, sass includes #error, #warn, #debug directives that will log things to the terminal to verying degrees of of noisiness.
#error "the value of $length is `#{$length}`"
More info on those can be found here

Scss for loop generated with space [duplicate]

I am trying to create dynamic values, but have failed so far. The created pixel value seems to lose the ability to be used in calculations.
$numericValue: 30;
$pixelValue: $numericValue+px;
// also tried $pixelValue: #{$numericValue}px;
$calc: $pixelValue * 2;
// also tried $calc: unquote($pixelValue) * 2;
This throws an error
Syntax error: Undefined operation: "30px times 2"
The trick is to use * 1px when you want to add a unit. Using +px or interpolation (#{$numericValue}px) turns it into a string.
$numericValue: 30;
$pixelValue: $numericValue * 1px;
$calc: $pixelValue * 2;
You need to define the unit you will use. If you are working with pixels you can create dynamic values adding px to the $numericValue.
$numericValue: 30px;
$pixelValue: $numericValue;
$calc: $pixelValue * 2;

Building of a string, which depends on variable number of parameters

My question is: how to build a string in Less, which depends on variable number of parameters. For instance, I would like to make a mixin, which helps me to write #font-face CSS rules. So I need to build src:... fonts property for arbitrary number of formats (.eot, .ttf, .oft, .woff, .woff2, .svg) of my font. Here is my Less loop to process all font formats in list:
// #some-types - it is my font formats list, just smth. like 'otf', 'eot',...
// #old-src-value - it is string with src for my font from previous loop
// #counter - it is my loop counter
.make-font-src(#some-types; #old-src-value; #counter) when (#counter <= length(#some-types)) {
// Here we get next font format from #some-types
#font-type: extract(#some-types, #counter);
// Used for building 'format("opentype")' - like part of src value string
.get-font-format(#font-type);
// Building a part of src value string for this iteration
#src-value: e('#{old-src-value}, url("#{font-path}#{font-filename}.#{font-type}") format("#{font-format}")');
// Recursive call of this mixin for looping
.make-font-src(#some-types; #src-value; (#counter + 1));
}
So I'm stuck in how to fetch complete src value string, when all font formats will be processed in the loop? Also please refer to this codepen demo.
As mentioned in my comment, this would not cause a recursive definition error because you have assigned the value to a different variable and then used it. However, it seems like Less is processing the property-value setting line as soon as the first iteration of the loop is completed. You can verify this by changing the counter value for the first iteration itself to 2 or more.
One solution (a better approach to the problem in my opinion) would be to use the property merging with comma feature and set the property-value pair directly like in the below snippet:
.make-font-src(#some-types; #counter) when (#counter <= length(#some-types)) {
#font-path: 'some/test/path/';
#font-filename: 'Arial';
#font-type: extract(#some-types, #counter);
src+: e('url("#{font-path}#{font-filename}.#{font-type}") format("#{font-type}")');
.make-font-src(#some-types; (#counter + 1));
}
div.test {
.make-font-src('eot', 'woff', 'svg'; 1);
}
This when compiled would produce the following output:
div.test {
src: url("some/test/path/Arial.eot") format("eot"),
url("some/test/path/Arial.woff") format("woff"),
url("some/test/path/Arial.svg") format("svg");
}
Finally, I found my own solution: if we add special 'getter' mixin with guard, which triggered on last iteration of the loop, we can get full src value from our loop mixin.
.getter(#cond; #list) when (#cond = length(#list)) {
#font-src-full: #src-value;
}
Here is a fiddle with demo

How to Generate Placeholders in Stylus

I'm looking to generate placeholders and variables that can change depending on configured proportions such as the following:
$small-margin-top
$large-margin-top
$small-padding-bottom
Where each placeholder applies the corresponding, generated variable to the rule:
$small-margin-top
margin-top $marginsmall
$large-margin-top
margin-top $marginLarge
$small-padding-bottom
margin-bottom $marginSmall
I have statically defined the variables for now:
/* Margin */
$margin = 1rem
$marginsmall = $margin / $multiplier
$marginlarge = $margin * $multiplierLarge
$marginmini = $marginSmall / $multiplierLarge
But I get an error:
TypeError: expected "name" to be a string, but got ident:marginmini
properties = margin padding
proportions = mini small medium large
directions = top left bottom right
for property in properties
for proportion in proportions
for direction in directions
${property}-{direction}-{proportion}
{property}-{direction} lookup(property + proportion)
How can I generate placeholders for my proportions variable, such that the generated placeholders may be extended later (#extend $margin-large)?
EDIT: here is the working solution
The lookup bif accepts a string, and you are passing an ident (margin, padding, etc. without quotes). You can convert them to string by using concatenation. Also, you miss a $ sign:
properties = margin padding
proportions = mini small medium large
directions = top left bottom right
for property in properties
for proportion in proportions
for direction in directions
${proportion}-{property}-{direction}
{property}-{direction} lookup('$' + property + proportion)

Resources