Nested Mixins or Functions in Sass

Nested mixins or functions in SASS

yeah you already doing it right. You can call first mixin in second one. check this pen http://codepen.io/crazyrohila/pen/mvqHo

SASS nested mixins issue

One easy to use approach I could think of is the one where you extend your margin mixin by conditionals and optional parameters to be able to exclude specific media queries if necessary.

@mixin margin($sm: true, $lg: true) {
@if $sm {
@include sm {
margin: 10px;
}
}
@if $lg {
@include lg {
margin: 20px;
}
}
}

.margin {
@include margin;
}

.margin-only-on-lg {
@include margin(false, true);
}

Using the mixin is still simple and the use of media queries is only necessary in the mixin itself. It is also pretty robust, so that in case a developer is not aware of the optional parameters he can do the following without breaking the logic.

.foo {
@include lg {
@include margin;
}
}

But of course it outputs some unnecessary CSS. If you see a problem here and/or if you want to have a more flexible approach of passing different concrete margin values as parameters, the following modification in combination with warnings for missing optional parameters at compile time (see my answer there) might be a better approach:

@mixin margin($sm: false, $lg: false) {
@include sm {
margin: warn-on-false("margin()", $sm, 10px);
}
@include lg {
margin: warn-on-false("margin()", $sm, 20px);;
}
}

.margin {
@include margin(null, null); // I'm aware of the parameters, but use the default values
}

.margin-only-on-lg {
@include margin(0, null); // set margin to 0 on small screen size; use default for lg
}

This way the above (undesired) way of defining the .foo class due to a lack of knowing the optional parameters results in a warning at compile time and in addition the developer can use different margin values in special cases. Of course, it would also be possible to simply go with the boolean parameters and make them mandatory.

SCSS Mixin Function for UL LI nested list

Here is a simple mixin:

@mixin leftPosition($startingValue: 0, $increment: 40, $max: 10) {
$selector: '';

@for $i from 0 through $max - 1 {
$selector: $selector + ' li';
#{$selector} span::before {
left: #{$startingValue - $i * $increment}px;
}
}
}

It takes few parameters:

  • $startingValue is the first value for your left property. It defaults to 0, but in your example you'd want -8.
  • $increment is the incremental value you want, heree you want 40.
  • $max is the number of li you'll get.

You can use it like this:

ul {
@include leftPosition($startingValue: -8)
}

And it will output:

ul li span::before {
left: -8px;
}
ul li li span::before {
left: -48px;
}
ul li li li span::before {
left: -88px;
}
ul li li li li span::before {
left: -128px;
}
ul li li li li li span::before {
left: -168px;
}
ul li li li li li li span::before {
left: -208px;
}
ul li li li li li li li span::before {
left: -248px;
}
ul li li li li li li li li span::before {
left: -288px;
}
ul li li li li li li li li li span::before {
left: -328px;
}
ul li li li li li li li li li li span::before {
left: -368px;
}

Of course, you can't get the value of $max from the HTML. It's a value you'll have to define yourself.

Is there a way to use @mixin within a @function in SASS/SCSS?

No. The Sass documentation states that the @function at-rule

...can only contain universal statements, as well as the @return at-rule which indicates the value to use as the result of the function call.

An @include at-rule isn't a universal statement.

Using sass @function inside @for

You are doing it right, but you need to send the $i value without interpolation:

@for $i from 0 through 200 {
@each $position, $prefix in $short-margins{
.#{$prefix}-#{$i} {
margin-#{$position}: single-px-to-rem($i);
}
}
}


Related Topics



Leave a reply



Submit