【问题标题】:How to use @each in mix includes in Sass?如何在 Sass 中混合使用 @each?
【发布时间】:2019-06-19 11:24:17
【问题描述】:

我正在尝试动态生成我的@include 并动态插入@content,这样我就不必不断重复代码..

但是我收到以下错误,我想知道我做错了什么以及是否可以使用包含来执行此操作,或者我必须手动输入所有变量名称。

$ node-sass scss/_sixbase-grid.scss ../app/src/public/css/sixbase-grid.min.css --output-style expanded
{
  "status": 1,
  "file": "C:/Users/THIAGOSAAD/Documents/DEVELOPMENT/SIXBASE/PERSONAL PROJECTS/githubcompare/build/scss/_sixbase-grid.scss",
  "line": 40,
  "column": 12,
  "message": "no mixin named media-",
  "formatted": "Error: no mixin named media-\n        on line 40 of scss/_sixbase-grid.scss\n>>   @include media-#{$media-key} {\n\n   -----------^\n"
}
error Command failed with exit code 1.

SIXBASE-GRID.SCSS

/*!
 * Sixbase Flexbox v1.0.0 (https://sixbase.tech/)
 * Copyright 2019 Sixbase.
 * Licensed under GNU General Public License v3.0 (https://github.com/sixbase-tech/githubcompare/blob/master/LICENSE)
 */

@import './mixins/media-queries';

$container-map: (
  flex:   ( display: flex ), 
  inline: ( display: inline )
);

$flex-direction-map: (
  row:            ( flex-direction: row ),
  row-reverse:    ( flex-direction: row-reverse ),
  column:         ( flex-direction: column ),
  column-reverse: ( flex-direction: column-reverse )
);

$media-map: (
  smartphone-xs: ( type: 'xs' ), 
  smartphone-sm: ( type: 'sm' ), 
  tablet-md:     ( type: 'md' ), 
  tablet-lg:     ( type: 'lg' ), 
  desktop:       ( type: 'xl')
);

* {
  &::before,
  &::after {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
  }
}


@each $media-key in $media-map {
  @include media-#{$media-key} {
   @each $display-key, $display-type in $container-map {
       .container-#{map-get($map: $media-key, $key: type )}-#{$display-key} { 
         display: map-get($map: $display-type, $key: display ); 
       }
     }
  }
}

MEDIA_QUERIES.SCSS

$xs-width: 320px;
$sm-width: 576px;
$md-width: 768px;
$lg-width: 992px;
$xl-width: 1200px;

@mixin media-smartphone-xs {
    @media only screen and (min-width: $xs-width) {
        @content;
    }
}

@mixin media-smartphone-sm {
    @media only screen and (min-width: $sm-width) {
        @content;
    }
}

@mixin media-tablet-md {
    @media only screen and (min-width: $md-width) {
        @content;
    }
}

@mixin media-tablet-lg {
    @media only screen and (min-width: $lg-width) {
        @content;
    }
}

@mixin media-desktop {
    @media only screen and (min-width: $xl-width) {
        @content;
    }
}

【问题讨论】:

    标签: sass node-sass


    【解决方案1】:

    问题出在:@include media-#{$media-key} {...},因为你不能在@mixin 中使用插值。看到这个帖子,很清楚这个issueHow to define a dynamic mixin or function name in SASS?

    所以,我们必须使用另一种方式。一个解决方案可以是创建一个通用的 mixin 并使用它的参数。像这样的:

    @mixin general-media($width){
      @media only screen and (min-width: $width) {
        @content;
      }
    }
    

    之后,我选择在 $media-map 地图中添加您的宽度值并将它们与该 mixin 一起使用(我尝试使用您的代码):

    $media-map: (
      smartphone-xs: ( type: 'xs', width: $xs-width ), 
      smartphone-sm: ( type: 'sm', width: $sm-width ), 
      tablet-md:     ( type: 'md', width: $md-width ), 
      tablet-lg:     ( type: 'lg', width: $lg-width ), 
      desktop:       ( type: 'xl', width: $xl-width )
    );
    

    这是你的循环,有一些变化:

    @each $media-key, $media-type in $media-map {
      @include general-media(map-get($media-type, 'width')) {
       @each $display-key, $display-type in $container-map {
           .container-#{map-get($media-type, 'type' )}-#{$display-key} { 
             display: map-get($map: $display-type, $key: display ); 
          }
        }
      }
    }
    

    这是所有的代码:

    /* MEDIA_QUERIES.SCSS */
    
    $xs-width: 320px;
    $sm-width: 576px;
    $md-width: 768px;
    $lg-width: 992px;
    $xl-width: 1200px;
    
    @mixin general-media($width){
      @media only screen and (min-width: $width) {
        @content;
      }
    }
    
    /* SIXBASE-GRID.SCSS */
    
    $container-map: (
      flex:   ( display: flex ), 
      inline: ( display: inline )
    );
    
    $flex-direction-map: (
      row:            ( flex-direction: row ),
      row-reverse:    ( flex-direction: row-reverse ),
      column:         ( flex-direction: column ),
      column-reverse: ( flex-direction: column-reverse )
    );
    
    $media-map: (
      smartphone-xs: ( type: 'xs', width: $xs-width ), 
      smartphone-sm: ( type: 'sm', width: $sm-width ), 
      tablet-md:     ( type: 'md', width: $md-width ), 
      tablet-lg:     ( type: 'lg', width: $lg-width ), 
      desktop:       ( type: 'xl', width: $xl-width )
    );
    
    * {
      &::before,
      &::after {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }
    }
    
    @each $media-key, $media-type in $media-map {
      @include general-media(map-get($media-type, 'width')) {
       @each $display-key, $display-type in $container-map {
           .container-#{map-get($media-type, 'type' )}-#{$display-key} { 
             display: map-get($map: $display-type, $key: display ); 
          }
        }
      }
    }
    

    输出:

    *::before, *::after {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    
    @media only screen and (min-width: 320px) {
      .container-xs-flex {
        display: -webkit-box;
        display: -webkit-flex;
        display: -ms-flexbox;
        display: flex;
      }
      .container-xs-inline {
        display: inline;
      }
    }
    
    @media only screen and (min-width: 576px) {
      .container-sm-flex {
        display: -webkit-box;
        display: -webkit-flex;
        display: -ms-flexbox;
        display: flex;
      }
      .container-sm-inline {
        display: inline;
      }
    }
    
    @media only screen and (min-width: 768px) {
      .container-md-flex {
        display: -webkit-box;
        display: -webkit-flex;
        display: -ms-flexbox;
        display: flex;
      }
      .container-md-inline {
        display: inline;
      }
    }
    
    @media only screen and (min-width: 992px) {
      .container-lg-flex {
        display: -webkit-box;
        display: -webkit-flex;
        display: -ms-flexbox;
        display: flex;
      }
      .container-lg-inline {
        display: inline;
      }
    }
    
    @media only screen and (min-width: 1200px) {
      .container-xl-flex {
        display: -webkit-box;
        display: -webkit-flex;
        display: -ms-flexbox;
        display: flex;
      }
      .container-xl-inline {
        display: inline;
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-11-19
      • 2014-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多