Less Missing closing } - visual-studio-2013

I have the following code and only this code in my Less file.
#iterations: 100;
.width-loop (#i) when (#i > -1)
{
(~".w#{i}")
{
width: ~"#{i}% !important";
}
.width-loop(#i - 1);
}
.width-loop(#iterations);
the result is like this.
.w100 {width 100% !important; }
.w99 {width 99% !important; }
......
etc
However, when I build my project, this error pops up in my error window.
Less: Missing closing '}'
Where am I missing a }? The error window popping up is most distracting.
When I view the output in the browser, the style classes list correctly.

You are calling the function wrong. Do it like this:
#iterations: 100;
.width-loop (#i) when (#i > -1)
{
.w#{i}
{
width: ~"#{i}% !important";
}
.width-loop(#i - 1);
}
.width-loop(#iterations);

Related

SASS prefix custom element

I try to prefix a custom element that looks like this <myprefix-toggle></myprefix-toggle>. It does not work. However if I add # as if it would be an id it does compile. Why and how can I get around it?
Works
$prefix: "myprefix-";
#{$prefix}toggle {
background: red;
}
Does not work
$prefix: "myprefix-";
{$prefix}toggle {
background: red;
}
The error I get is probably not that related to the real issue...
Error: expected ':' after $prefix in assignment statement
If it's of importance I use gulp-sass to compile the sass to css.
The hashtag and the curly brackets is the Sass syntax for interpolation #{ ... }
$prefix: "myprefix-";
// CSS output
#{$prefix}toggle { ... } // myprefix-toggle { ... }
.#{$prefix}toggle { ... } // .myprefix-toggle { ... }
##{$prefix}toggle { ... } // #myprefix-toggle { ... }

Why doesn't SASS resolve the calculation?

Why doesn't SASS resolve the calculation?
$animation-speed-half-life: 1s;
#for $i from 0 through 31 {
&:nth-child(#{$i}) {
transition-delay: #{$animation-speed-half-life - $animation-speed-half-life / $i};
}
}
Instead it outputs transition-delay: 1s - 1s/1;
I'm not sure why Sass won't calculate that but you don't actually need to interpolate the value of transition-delay, as there's no CSS going on around it.
This would be my implementation of your code:
#mixin incremental-transition-delay($child-count, $half-life: 1s) {
#for $i from 1 through $child-count {
&:nth-child(#{$i}) {
transition-delay: $half-life - $half-life / $i;
}
}
}
.thing {
#include incremental-transition-delay(32, 1s);
}
Did you already debug it?
I tested your code at Sassmeister (SASS v3.4.21), and it shows me a reference error:
Base-level rules cannot contain the parent-selector-referencing
character '&'.
DEBUG
$animation-speed-half-life: 1s;
$i: 1;
$test: #{$animation-speed-half-life - $animation-speed-half-life / $i};
#error $test; // this will render '0s' as expected
.parentElement { // comment this to show the reference error
#for $i from 0 through 31 {
&:nth-child(#{$i}) {
transition-delay: #{$animation-speed-half-life - $animation-speed-half-life / $i};
}
}
}
Sassmeister Fiddle
Not sure, if that's your complete code or just a snippet but it warns me the error I quoted above. It looks for a parent element which doesn't exist. Probably, that's why in your version it won't calculate. The .parentElement is just a dummy to provide you the working way.
POSSIBLE FIX
Add a #if-condition that checks if a parent element exists:
#if & { ... }
So basically wrap the condition around the loop:
#if & {
#for $i from 0 through 31 {
&:nth-child(#{$i}) {
transition-delay: #{$animation-speed-half-life - $animation-speed-half-life / $i};
}
}
}
Sassmeister Fiddle
The if & { .. statement is optional. Just wanted to show you how to bug out the error. I am not sure if your SASS version still interpolates the calculation during an error or not.
My own personal way would be using a placeholder without the if & statement because a placeholder functions as a parent element and no error will occur. Even if the element doesn't exist but that's what placeholders are for:
%test {
#for $i from 0 through 31 {
&:nth-child(#{$i}) {
transition-delay: #{$animation-speed-half-life - $animation-speed-half-life / $i};
}
}
}
parent {
#extend %test;
}
Sassmeister Fiddle
A Mixin would work also but your loop doesn't need any parameter to function so a placeholder should do it.

Avoid repeat the same mixin in Sass

I have this Mixin for padding utility:
Sass code:
$padding: (
top: "top",
right: "right",
bottom: "bottom",
left: "left",
all: "all"
);
#mixin no-padding($map) {
#each $padding-side, $side in $map {
#if $side == 'all' {
& {
padding: 0 !important;
}
} #else {
&-#{$side} {
padding-#{$side}: 0 !important;
}
}
}
}
Use of it:
.u-noPadding {
#include no-padding($padding);
}
I want to use the same Mixin but now for margin, is there any solution to avoid repeating the same mixin and make a good use of best practices?
#mixin no($type,$sides:null) {
$i:0 !important;
#if $sides == null {
#{$type}:$i;
} #else {
#each $side in $sides {
#{$type}-#{$side}:$i;
}
}
}
.u-noPadding {
#include no(padding, top left etc...); // choose any side separated with a space
}
.u-noMargin {
#include no(margin); // instead of 'all', type nothing
}
Like this? Your $sides will be stored in a temporary map automatically if your second parameter is set, no need extra map for this.
About the second parameter: If you want no sides, let it empty and all sides will have 0. Similiar to your 'all' idea.. it's shorter.

Conditionally output a part of SCSS rule selector

I would like to specify an additional default shortcut class to a set of classes, similarly to that
#each $pos, $some-css-rules in ("left": ..., "right": ..., ...) {
#if $pos == "left" {
.block,
}
.block-#($pos) {
...
}
}
that would be outputted as
.block,
.block-left {
...
}
.block-right {
...
}
However, it will stumble over .block, syntax error.
.block-left cannot be replaced here with .block.left because $pos will collide with existing classes (.left, etc).
I would prefer to avoid .block { #extend .block-left } if possible, there is a considerable amount of similar rules that will gain a lot of WET code this way.
Is there a way to conditionally output a part of rule selector? How can both SCSS and CSS be kept DRY in a pattern like that?
I'm not sure if I understand the question but I achieve the output CSS based on your code. I put the #if directive inside the selector to compare with $pos variable. Here is my code:
SASS
#each $pos, $some-css-rules in ("left": red, "right": blue) {
.block-#{$pos} {
#if $pos == "left" {
#at-root .block, &{
color:$some-css-rules;
}
}
#else{
color:$some-css-rules;
}
}
}
Output
.block, .block-left {
color: red;
}
.block-right {
color: blue;
}

Sass loop: start from second instance of this element

I have a series of divs in a step type layout. I am learning to use Scss at the moment and I thought maybe a mixin could work through the 12 divs and arrange them for me. So far I've got:
#mixin steps(){
$stepBlocks: 12;
#for $i from 1 through $stepBlocks {
.steps-#{$i} {
position: absolute;
top: (($i * 296) + px);
display: block;
}
}
}
This is what my div structure looks like:
I've made a HTML mockup as well:
http://jsfiddle.net/vdecree/CGGyL/
As you can see, the fiddle works fine, however how can I negate the effect of the first one? I need the first element to be top: 0; is there an if statement I can use? If you think you've a better way in which I can do this, I'd appreciate any help.
What you're likely wanting to is start with an offset of 0, rather than 296px.
#mixin steps(){
$stepBlocks: 12;
#for $i from 1 through $stepBlocks {
.steps-#{$i} {
position: absolute;
top: ($i - 1) * 296px;
display: block;
}
}
}

Resources