SASS Mixin Syntax for '$' Prefix [duplicate] - sass

This question already has answers here:
Sass Interpolation of Mixin, Function, and Variable names
(3 answers)
Closed 8 years ago.
I'm working on a simple mixin to use in conjunction with Grunt Spritesmith. Here is what I've written so far...
#mixin svg($svg, $height, $width) {
background-image:url(../../images/svg/#{$svg}.svg);
background-repeat:no-repeat;
display:block;
height:$height + px;
width:$width + px;
.no-svg & {
#include sprite($#{$png});
}
}
And I would use it like this...
#include svg("logo", 50, 100);
The issue I'm having is that I'm passing in just the name of the image (in this case just 'logo') to use in the background-image url, but then I need to prefix the #include sprite mixin with a dollar like so...
#include sprite($logo);
So all I need to know really is how I would format this line in Sass so that it spits out the passed in $svg variable with a $ prefixing it. This is the line which needs tweaking #include sprite($#{$png}); Thanks.

I'm a bit confused, why don't you just apply #include sprite(#{$svg})
#mixin svg($svg, $height, $width) {
background-image:url(../../images/svg/#{$svg}.svg);
background-repeat:no-repeat;
display:block;
height:$height + px;
width:$width + px;
.no-svg & {
#include sprite(#{$svg});
}
}
#mixin sprite($value) {
background-image:url(../../images/png/#{$value}.png);
...
}
div {
#include svg("logo", 50, 100);
}
OUTPUT
div {
background-image: url(../../images/svg/logo.svg);
background-repeat: no-repeat;
display: block;
height: 50px;
width: 100px;
}
.no-svg div {
background-image: url(../../images/png/logo.png);
...
}
An example : http://sassmeister.com/gist/cdccd858780acbf2d144

Related

use variable defined for one sass mixin in another sass mixin

I'm trying to use a var defined for one mixin in another mixin.
In my case, I definee the $gutter variable in the container() mixin.
I don't want to define it again for the col() mixin, so I was trying to get it into the col() mixin.
Here is what I've done so far:
#mixin container($gutter, $placeholder:"cols") {
margin: 0 -#{$gutter / 2};
%#{$placeholder} {
margin-left: #{$gutter / 2};
margin-right: #{$gutter / 2};
}
}
#mixin cols($cols, $placeholder:"cols") {
#extend %#{$placeholder};
width: #{(100% / $cols) - $gutter};
}
.wrap {
#include container(2%);
> .half {
#include cols(2);
}
> .third {
#include cols(3);
}
> .fourth {
#include cols(4);
}
}
The css result I need is the following:
.wrap {
margin: 0 -1%;
}
.wrap > .half, .wrap > .third, .wrap > .fourth {
margin-left: 1%;
margin-right: 1%;
}
.wrap > .half {
width: 48%;
}
.wrap > .third {
width: 31.33333%;
}
.wrap > .fourth {
width: 23%;
}
Is there a way to do this? It fails in line 11 because $gutter is undefined. A global variable isn't the solution i need, because I have to use this mixin in different breakpoints with different gutters. So for each breakpoint will define container() and cols() for the elements again.
You are creating a variable inside a mixin. Variables inside mixins are local they are not global. If you want to create a global variable from a mixin then you have to use the !global flag
you can rewrite the container mixin like this
#mixin container($gutter, $placeholder:"cols") {
$gutter: $gutter !global;
margin: 0 -#{$gutter / 2};
%#{$placeholder} {
margin-left: #{$gutter / 2};
margin-right: #{$gutter / 2};
}
}

Shorthand syntax gutters being ignored for span mixin

I've set global settings for susy:
$susy: (
columns: 8,
gutters: 1/4,
);
I want to override the gutters for a couple of span
.tile-left {
#include span(1 of 2 1px);
}
.tile-right {
#include span(1 at 2 of 2 1px);
}
Generated css
.tile-left {
width: 44.44444%;
float: left;
margin-right: 11.11111%;
}
.tile-right {
width: 44.44444%;
float: right;
margin-right: 0;
}
I've also tried these and these don't seem to be working either
#include span(1 of 2 no-gutters);
&
#include span(1 of 2 (gutter-override: 1px));
Looks like the "1px" argument didnt work because gutters can only be defined by a ratio value; Documentation
Furthermore, I've solved my issue of wanting fluid elements and a static gutter by
doing this:
.tile-left {
#include span(1 of 2 (gutter-override: no-gutters, gutter-position: inside-static));
border-right: 1px solid #E5E5E5;
}
.tile-right {
#include span(1 of 2 (gutter-override: no-gutters, gutter-position: inside-static));
}
It looks like when you remove the gutters by passing "gutter-override: no-gutters" it calculates the width with gutters, but then removes the margins; By putting the gutters/margin inside by passing "gutter-position: inside-static" the with is calculated to span to 100% without gutters.
It's not entirely clear in your post what you are trying to achieve. #include span(1 of 2 no-gutters); should remove the gutter output, but won't change the math. If your goal is to change the math so there are no gutters, #include span(50% no-gutters); might be the best option. Or #include span(1 of 2 (gutters: 0)); should give you the same output.
UPDATE: even #include span(1 of 2 0); seems to work. The 0 is understood as a valid gutter ratio.

Only add unit on valid number

I'm trying to do a mixin that have optional arguments. This is a simplified version:
#mixin marginCalculator($size, $size2:"") {
margin: $size * 1px unquote($size2 * 1px);
}
I'm just passing in numbers as arguments. But i only want the first one to be mandatory. No problem if it only would output the number but i need to add a unit to it.
As can be seen in the snippet above i'm trying to multiplicate 1px with "" which ouputs an error message. As it should! But i was hoping for the empty quote to be returned. Is there another way to achieve this?
You have 2 options:
Check the type of the value being passed in
#mixin marginCalculator($size, $size2: "") {
margin: ($size * 1px) (if(type-of($size2) == number, $size2 * 1px, null));
}
Loop over a list
This is a much better solution since it will allow you to gracefully handle 3-value margins as well.
#mixin marginCalculator($size...) {
$xs: ();
#each $s in $size {
$xs: append($xs, $s * 1px);
}
margin: $xs;
}
.foo {
#include marginCalculator(1);
#include marginCalculator(1, 2);
#include marginCalculator(1, 2, 3);
}
Alternately:
#mixin marginCalculator($sizes) {
$xs: ();
#each $s in $size {
$xs: append($xs, $s * 1px);
}
margin: $xs;
}
.foo {
#include marginCalculator(1);
#include marginCalculator(1 2);
#include marginCalculator(1 2 3);
}
Output:
.foo .foo {
margin: 1px;
margin: 1px 2px;
margin: 1px 2px 3px;
}
You can use an if() function to check if it has no value:
#mixin marginCalculator($size, $size2:"") {
margin: ($size * 1px) if($size2!="", $size2 * 1px, null);
}
Here, i check it against the default, an empty string, and return the calculation if it isn't that, and null if it is. If we return an empty string, it'll cause a CSS error.

New to scss, "rule is empty"?

see this codepen
it is super basic
$span1Width: 10;
$marginWidth: 5;
#mixin span-width($spannr) {
width: $span1Width * $spannr *1%;
*width: $marginWidth* $spannr -1 *1%;
}
div{
#use span-width(10);
}
resulting in "empty rule" when doing a analyse css with codepen.
If you check the example on sass documentation on how to use mixins you can see:
$color: white;
#mixin colors($color: blue) {
background-color: $color;
#content;
border-color: $color;
}
.colors {
#include colors { color: $color; }
}
So you should use #include and { } instead. Like (using default 5 in this example):
$span1Width: 10;
$marginWidth: 5;
#mixin span-width($spannr: 5) {
width: $span1Width * $spannr *1%;
*width: $marginWidth* $spannr -1 *1%;
}
div{
#include span-width{ spannr: 10};
}
That should give you the correct result

Is there a way to use an argument in a mixin to generate a variable name within the mixin with SASS? [duplicate]

This question already has answers here:
Creating or referencing variables dynamically in Sass
(7 answers)
Closed 7 years ago.
Regarding the question, here's an example of what I'm trying to do but I have a feeling that interpolation with SASS doesn't work in outputting variable within a mixin using an argument.
$red: #f00;
#mixin color-accent-class($color) {
.#{$color}-accent {
color: $#{$color};
}
}
#include color-accent-class(red);
Ultimately I'm trying to make the repetitive code below DRY so I'm not repeating myself all sloppy style and I'm wondering if it should be done with #function and/or #each or some other looping action with SASS. Thanks in advance for any guidance!
$blue: #2a62a7;
$red: #db0042;
$purple: #5b3b9f;
$orange: #f7911a;
$light-blue: #46aeed;
$green: #49b842;
#mixin product-accent($color-name, $hexval) {
.product-accent-#{$color-name} {
img {
border: {
left: {
style: solid;
width: 10px;
color: $hexval;
}
}
}
h3, b {
color: $hexval;
}
.button {
#extend .button.#{$color-name};
}
}
}
#include product-accent(black, #000);
#include product-accent(blue, $blue);
#include product-accent(red, $red);
#include product-accent(purple, $purple);
#include product-accent(orange, $orange);
#include product-accent(light-blue, $light-blue);
#include product-accent(green, $green);
Big thanks to #martin-turjak for help with this. Using SASS lists, nth() and a #for loop is what did the trick. Please chime in if there's a cleaner way to do this.
$color-names: black, blue, red, purple, orange, light-blue, green;
$color-hexvals: #000, $blue, $red, $purple, $orange, $light-blue, $green;
#for $i from 1 through length($color-names) {
#include product-accent(nth($color-names, $i), nth($color-hexvals, $i));
}

Resources