Daria Garmash
Daria Garmash

Reputation: 53

how to use variable for @include name inide @each loop SCSS

I want to replace this SCSS code with @each usage.

body{
  @include us(){
    @include define-breakpoint("us")
  }
  @include xs(){
    @include define-breakpoint("xs")
  }
  @include sm(){
    @include define-breakpoint("xs")
  }
  @include md(){
    @include define-breakpoint("md")
  }
  @include lg(){
    @include define-breakpoint("lg")
  }
  @include xl(){
    @include define-breakpoint("xl")
  }
}

When I use @each function compiler throws out an error - invalid css with @include #{$bp}(){...}

$list: us xs sm md lg xl;
  @each $bp in $list{
    body{
    @include #{$bp}(){
      @include define-breakpoint("#{$bp}")
    }
    }
  }

Does everybody know how to handle this error? Appreciate any help

Upvotes: 2

Views: 2550

Answers (1)

Daisi
Daisi

Reputation: 2418

The problem with this code is that interpolation can't be used to convert a variable to an identifier. The Sass compiler won't allow it. At the point where you interpolate $bp, the compiler expects an identifier. It will treat anything at that point as an identifier and not something that should be interpolated.

From your code it appears you've defined several mixins with @content passed within the block like so

@mixin us() { @content; }
@mixin sm() ( @contnet; }

which is why they are called like so

@include us(){
  @include define-breakpoint("us");
}

You could refactor your code to make use of only one mixin since the only thing that's actually changing is the code in the block.

$list: us xs sm md lg xl;

@mixin screen-size() { @content; }

body {
  @each $size in $list {
    @include screen-size() {
      @include define-breakpoint($size);
    }
  }
}

Another option would be to define the mixin to take a parameter instead and have the code within that block include the define-breakpoint mixin passing the parameter as an argument.

$list: us xs sm md lg xl;

@mixin screen-size($size) { 
  @include define-breakpoint($size); 
}

body {
  @each $size in $list {
    @include screen-size($size);
  }
}

UPDATED ANSWER

To achieve the added functionality specified in your code you can make the following adjustments to the previous answer

//list now takes media query also
$list: 'us' '(max-width: 519px)',
       'xs' '(min-width: 520px) and (max-width: 767px)',
       'sm' '(max-width: 768px)',
       'md' '(min-width: 769px)',
       'lg' '(min-width: 519px) and (max-width: 960px)',
       'xl' '(min-width: 961px)';

//mixin takes media query as argument
@mixin screen-size($query) {
  @media #{$query} {
    @content;
  }
}

body {
  @each $map in $list {
    @include screen-size( nth($map, 2) ) {
      @include define-breakpoint( nth($map,1) );
    }
  }
}

Hope this solves your problem

Upvotes: 4

Related Questions