How to Do Math Within a Less CSS String Interpolation

Can I do math within a LESS css string interpolation?

Not Within the String Itself, but...

If you separate it out of the string, then do a second interpolation following (note the 2nd ~), this works:

@tablet-landscape-only: ~"only screen and (min-width: "(@bp-tablet-portrait + 1) ~") and (max-width: @{bp-tablet-landscape})";

To produce this:

@media only screen and (min-width:  769px ) and (max-width: 1024px) {
div#header {
background: #000;
}
}

What is the right syntax for .less variable interpolation?

So if I understand correctly, you want to give the width a value but without any units, and assign the units at the time of the call. I'm not sure why you would want to do that, but there are two ways that would work:

ONE: make the width a string and then do a string interpolation:

@width: '600';

.some-style
{
width: ~'@{width}px';
}

TWO: multiply by 1px:

@width: 600;

.some-style
{
width: @width * 1px;
}

I've left the above answers in place for a case of "unitless" numbers and how to add the unit later (as the question appeared to be at first). However, based on your comment let me explain why @width: 600px works. LESS does not see that as a string (as you mention you view it). Rather, it sees it as a number with units. To LESS 600px is not the string of characters (unless it is wrapped in quotes), but the number 600 in units of pixels. This is why it can do operations on it just fine, without you having to worry about it. It can do so whether those units are em or % or any other valid CSS unit.

Subtract from a value obtained through variable interpolation

The output of ~"@{breakpoint-@{breakpoint}}" is always a string and so the compiler just appends the number to the string instead of performing the math operation.

One way would be to use a temporary variable like shown below (have added only the part that needs modification) and then perform the arithmetic operation.

.Mq(@breakpoint; @rules; @maxMin: min) {
/* the rest of the mixin */

& when not (@maxMin = min) {
@temp: ~"breakpoint-@{breakpoint}";
@break: (@@temp - 1); /* the braces are mandatory, without which it again appends */
@query: ~"(max-width: @{break})";
@media screen and @query {@rules();};
}
}

/* the selector blocks and mixin calls */

Below are few things that I found while working on the solution which have left me stumped. I'm trying to find the reason and will update the answer when I do find it out.

  • The braces play an important role in the @break variable. Without it, the output in media query is still a concatenation. However, if the same variable is used outside the media query (in a normal property-value pair like prop: @break, it prints the subtracted value).
  • The below code returns concatenated value (800px - 1)

    @break: ~"@{breakpoint-@{breakpoint}}" - 1;
    prop: @break;
    whereas the below gives a "Operation on invalid type" compiler error.

    @break: ~"@{breakpoint-@{breakpoint}}";
    prop: @break - 1;
    while I can see the reason behind them (first one results in string concatenation whereas second says subtraction can't happen on a string value), I am a bit stumped as to why the behavior is not consistent between the two.

(You are definitely not a laughing stock. Though I knew the reason for the problem, it took time for me to find a solution.)

Escaping string in less and passing variables

Use string interpolation:

   filter: ~"progid:DXImageTransform.Microsoft.gradient(startColorstr=@{startColor}, endColorstr=@{endColor})";

Variable from string interpolation returns a non unit value

Nested interpolation i.e. ~"@{section-row-padding-size-@{size}}" is not officially supported in Less. (It works in current versions but may stop to work at any moment eventually).

The correct method to achieve what you want is:

.section-row-padding(@size) {
@var-name: "section-row-padding-size-@{size}";
@padding-size: @@var-name;
padding: (@padding-size * 2);
}

or shorter:

.section-row-padding(@size) {
@padding-size: "section-row-padding-size-@{size}";
padding: (@@padding-size * 2);
}

See "variable references" for @@ meaning.

The problem is caused by the @padding-size not interpreted as a px unit but rather as a string.

Exactly. Using ~"" is like saying to the compiler "do not interpreter this value, it's just some string with whatever value I want you to pass through". Thus the type of the value returned by ~"@{section-row-padding-size-@{size}}" in your example is not a number and it can't be used with arithmetic operations (hence: "Operation on an invalid type").

(A few links for "why ~"" should be avoided whenever possible": 1, 2, 3, 4 etc.).

Get Less variable value from string

(I cannot skip this to not provide an alt. answer since such "namespace emulation via variable name concatenation" is my most favourite bloody wrong Less pattern (unfortunately it is also the most widely spread one :().

Instead of emulating namespaces via using looong global variable names (doh#1 in most of programming languages and paradigms global variables are considered harmful since 1970's... :) and then assembling those variable names via the ugly concatenation syntax (doh#2, ~"@{@{@foo}}-@{bar}-seriously}?"), one can use normal namespaces with much more clean syntax:

.theme(beach) {
@font-color: #3d3d3d;
// other beach variables
}
.theme(ocean) {
@font-color: #d3d3d3;
// other ocean variables
}

@theme: beach;

.theme(@theme);

body {color: @font-color}

This is just one of possible variations (for more examples see:

  • Dynamic Variable Names with Less -> gist
  • How to thematize in lesscss
  • etc.)

How can I force LESS (css) to recognize a variable?

Try this:

@mediaVersion: 101;
#branding{ background: url("../img/branding.jpg?v@{mediaVersion}"); }

The section "String interpolation" at http://lesscss.org/#-variables shows that this should work.

Slashes (`/`) in CSS values when using Less (e.g. in `font` shorthand)

Just ran into this issue, the escape function (for less.js anyway) is:
e()
Like this

font: @weight @size e('/') @height "Helvetica Neue", Arial, "Liberation Sans", FreeSans, sans-serif;


Related Topics



Leave a reply



Submit