如何在 Sass 中使用 @each in mix includes?
How to use @each in mix includes in Sass?
我正在尝试动态生成我的@include 并动态插入@content,这样我就不必一直重复代码..
但是我收到下面的错误,我想知道我做错了什么,是否可以使用 include 来做到这一点,或者我必须手动输入所有变量名。
$ 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;
}
}
问题在这里:@include media-#{$media-key} {...}
'因为你不能在 @mixin
中使用插值。看到这个post,很清楚这个issue:How 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;
}
}
我正在尝试动态生成我的@include 并动态插入@content,这样我就不必一直重复代码..
但是我收到下面的错误,我想知道我做错了什么,是否可以使用 include 来做到这一点,或者我必须手动输入所有变量名。
$ 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;
}
}
问题在这里:@include media-#{$media-key} {...}
'因为你不能在 @mixin
中使用插值。看到这个post,很清楚这个issue:How 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;
}
}